以min(金额)加入表不起作用

时间:2016-04-26 15:43:42

标签: mysql sql left-join min

我有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 |

查询说明:

  • 获取所选项目(1,2)。
  • 获得最低出价 - MIN(b.amount)
  • 显示已提供出价的用户名 - 在p.id = b.user_id上的LEFT JOIN用户p(这不起作用或我做错了

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

2 个答案:

答案 0 :(得分:2)

不,您不一定要提取已经出价的user_id。您按item_id分组,因此每个项目获得一个结果行。因此,您正在聚合,并为每个列说出您希望为该项目看到的值。 E.g:

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

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

而是找到最低出价,然后再次使用您的出价表加入以查看已实际记录:

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;

答案 1 :(得分:0)

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

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();