加入 table 与 min(amount) 不起作用
Joining table with min(amount) does not work
我有 3 个表,但数据只从 2 个表中提取。
我正在尝试为所选项目获取最低出价并以最低出价显示用户名。
目前查询有效,直到我们显示用户名时,它显示错误的用户名,与出价不匹配。
下面是结构和查询的工作示例。
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
| 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 上左加入用户 p(这不起作用或者我做错了什么)
[注意] 我不能使用子查询,我在 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;
我有 3 个表,但数据只从 2 个表中提取。
我正在尝试为所选项目获取最低出价并以最低出价显示用户名。
目前查询有效,直到我们显示用户名时,它显示错误的用户名,与出价不匹配。
下面是结构和查询的工作示例。
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
| 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 上左加入用户 p(这不起作用或者我做错了什么)
[注意] 我不能使用子查询,我在 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;