加入 table 与 min(amount) 不起作用

Joining table with min(amount) does not work

我有 3 个表,但数据只从 2 个表中提取。

我正在尝试为所选项目获取最低出价并以最低出价显示用户名。

目前查询有效,直到我们显示用户名时,它显示错误的用户名,与出价不匹配。

下面是结构和查询的工作示例。

SQL Fiddle

MySQL 5.6 架构设置:

CREATE TABLE `bid` (
  `id` int(11) NOT NULL,
  `amount` float NOT NULL,
  `user_id` int(11) NOT NULL,
  `item_id` int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;


INSERT INTO `bid` (`id`, `amount`, `user_id`, `item_id`) VALUES
(1, 9, 1, 1),
(2, 5, 2, 1),
(3, 4, 3, 1),
(4, 3, 4, 1),
(5, 4, 2, 2),
(6, 22, 5, 1);

-- --------------------------------------------------------

CREATE TABLE `item` (
  `id` int(11) NOT NULL,
  `name` varchar(100) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;

INSERT INTO `item` (`id`, `name`) VALUES
(1, 'chair'),
(2, 'sofa'),
(3, 'table'),
(4, 'box');

-- --------------------------------------------------------

CREATE TABLE `user` (
  `id` int(11) NOT NULL,
  `name` varchar(100) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;


INSERT INTO `user` (`id`, `name`) VALUES
(1, 'James'),
(2, 'Don'),
(3, 'Hipes'),
(4, 'Sam'),
(5, 'Zakam');


ALTER TABLE `bid`
  ADD PRIMARY KEY (`id`);

ALTER TABLE `item`
  ADD PRIMARY KEY (`id`);

ALTER TABLE `user`
  ADD PRIMARY KEY (`id`);


ALTER TABLE `bid`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=7;

ALTER TABLE `item`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=5;

ALTER TABLE `user`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=5;

查询 1:

SELECT b.id, b.item_id, MIN(b.amount) as amount, b.user_id, p.name
FROM  bid b
LEFT JOIN user p ON p.id = b.user_id
WHERE b.item_id in (1, 2)
GROUP BY b.item_id
ORDER BY b.amount, b.item_id

Results:

| id | item_id | amount | user_id |  name |
|----|---------|--------|---------|-------|
|  5 |       2 |      4 |       2 |   Don |
|  1 |       1 |      3 |       1 | James |

查询说明:

[注意] 我不能使用子查询,我在 doctrine2(php 代码)中这样做,它限制了 mysql 子查询

您可以使用子查询解决这个问题。我不是 100% 确定这是否是最有效的方法,但至少它有效。

SELECT b1.id, b1.item_id, b1.amount, b1.user_id, p.name
FROM  bid b1
LEFT JOIN user p ON p.id = b1.user_id
WHERE b1.id = (
   SELECT b2.id
   FROM bid b2
   WHERE b2.item_id IN (1, 2)
   ORDER BY b2.amount LIMIT 1
)

这首先选择项目 1 或 2 的最低出价,然后使用该出价的 ID 查找您需要的信息。

编辑

你是说 Doctrine 不支持子查询。我没有经常使用 Doctrine,但是像这样的东西应该可以工作:

$subQueryBuilder = $entityManager->createQueryBuilder();
$subQuery = $subQueryBuilder
    ->select('b2.id')
    ->from('bid', 'b2')
    ->where('b2.item_id IN (:items)')
    ->orderBy('b2.amount')
    ->setMaxResults(1)
    ->getDql();

$queryBuilder = $entityManager->createQueryBuilder();
$query = $queryBuilder
    ->select('b1.id', 'b1.item_id', 'b1.amount', 'b1.user_id', 'p.name')
    ->from('bid', 'b1')
    ->leftJoin('user', 'p', 'with', 'p.id = b1.user_id')
    ->where('b1.id = (' . $subQuery . ')')
    ->setParameter('items', [1, 2])
    ->getQuery()->getSingleResult();

不,您不一定要获取出价的 user_id。您按 item_id 分组,因此每个项目得到一个结果行。因此,您正在聚合,并且对于每一列,您都说出您希望看到该项目的价值。例如:

  • MIN(b.amount) - 项目记录的最小数量
  • MAX(b.amount) - 项目记录的最大数量
  • AVG(b.amount) - 项目记录的平均数量
  • b.amount - 任意选择的项目记录的数量之一(因为有很多数量而您没有指定要查看的数量,DBMS 只是选择其中之一)

也就是说,b.user_id不一定是出价最低的用户,而只是出价用户中的一个随机用户。

而是找到最低出价并再次加入您的出价 table 以访问相关记录:

select bid.id, bid.item_id, bid.amount, user.id as user_id, user.name
from bid
join 
(
  select item_id, min(amount) as amount
  from bid
  group by item_id
) as min_bid on min_bid.item_id = bid.item_id and min_bid.amount = bid.amount
join user on user.id = bid.user_id
order by bid.amount, bid.item_id;