为什么以及如何找到拍卖获胜者查询?
Why and how does this finding the auction winner query work?
我的一个朋友提出了以下查询来查找获胜投注
SELECT b1.*
FROM bids as b1
LEFT JOIN bids AS b2 ON b1.item_id = b2.item_id AND b1.bid_price < b2.bid_price
WHERE b2.item_id IS NULL
它似乎工作正常,但我不明白它是如何工作的,也不知道它是偶然的还是结果总是一样。有人可以解释一下它是如何工作的,尤其是 b1.bid_price < b2.bid_price
如何与明显不存在的 b2.bid_price 一起工作吗?
这是转储:
CREATE TABLE `bids` (
`bid_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`bid_price` decimal(10,2) unsigned NOT NULL,
`user_id` int(11) unsigned NOT NULL,
`item_id` int(11) unsigned NOT NULL,
`bid_date_created` datetime NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`bid_id`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8mb4
INSERT INTO bids VALUES (1, 14000.33, 12, 1, '2021-10-27 19:07:21');
INSERT INTO bids VALUES (2, 13000.60, 6, 1, '2021-10-27 18:07:21');
INSERT INTO bids VALUES (3, 21000.00, 7, 4, '2021-10-29 18:07:21');
INSERT INTO bids VALUES (4, 17000.25, 6, 4, '2021-10-27 18:07:21');
INSERT INTO bids VALUES (6, 5500.00, 6, 7, '2021-11-21 11:46:17');
INSERT INTO bids VALUES (7, 1000.00, 6, 29, '2021-11-22 11:21:41');
INSERT INTO bids VALUES (8, 18000.00, 6, 1, '2021-11-23 11:21:11');
INSERT INTO bids VALUES (9, 110.00, 14, 30, '2021-11-28 15:24:56');
INSERT INTO bids VALUES (10, 120.00, 13, 30, '2021-11-28 15:25:11');
INSERT INTO bids VALUES (11, 159.00, 14, 30, '2021-11-28 15:25:19');
INSERT INTO bids VALUES (12, 170.00, 13, 30, '2021-11-28 15:25:34');
INSERT INTO bids VALUES (13, 200.00, 14, 30, '2021-11-28 15:25:57');
INSERT INTO bids VALUES (14, 250.00, 13, 30, '2021-11-28 15:26:02');
INSERT INTO bids VALUES (15, 6000.00, 14, 6, '2021-11-28 15:26:30');
INSERT INTO bids VALUES (16, 7300.00, 13, 6, '2021-11-28 15:26:44');
INSERT INTO bids VALUES (17, 10000.00, 14, 6, '2021-11-28 15:29:14');
查询使用 LEFT OUTER JOIN 来 try 来查找匹配 item_id
与 b1
相同的行 b2
,但是bid_price
大于 b1
.
中的值
左外连接的工作方式是,如果没有匹配项,则无论如何都会返回左侧 table (b1
) 的列,而 b2
的列是空的。如果我们在没有 WHERE 子句的情况下测试查询,您可以在示例数据中看到这一点。
mysql> SELECT b1.bid_id, b1.item_id, b2.bid_id, b2.item_id
FROM bids as b1 LEFT JOIN bids AS b2 ON b1.item_id = b2.item_id
AND b1.bid_price < b2.bid_price;
+--------+---------+--------+---------+
| bid_id | item_id | bid_id | item_id |
+--------+---------+--------+---------+
| 2 | 1 | 1 | 1 |
| 4 | 4 | 3 | 4 |
| 1 | 1 | 8 | 1 |
| 2 | 1 | 8 | 1 |
| 9 | 30 | 10 | 30 |
| 9 | 30 | 11 | 30 |
| 10 | 30 | 11 | 30 |
| 9 | 30 | 12 | 30 |
| 10 | 30 | 12 | 30 |
| 11 | 30 | 12 | 30 |
| 9 | 30 | 13 | 30 |
| 10 | 30 | 13 | 30 |
| 11 | 30 | 13 | 30 |
| 12 | 30 | 13 | 30 |
| 9 | 30 | 14 | 30 |
| 10 | 30 | 14 | 30 |
| 11 | 30 | 14 | 30 |
| 12 | 30 | 14 | 30 |
| 13 | 30 | 14 | 30 |
| 15 | 6 | 16 | 6 |
| 15 | 6 | 17 | 6 |
| 16 | 6 | 17 | 6 |
| 3 | 4 | NULL | NULL |
| 6 | 7 | NULL | NULL |
| 7 | 29 | NULL | NULL |
| 8 | 1 | NULL | NULL |
| 14 | 30 | NULL | NULL |
| 17 | 6 | NULL | NULL |
+--------+---------+--------+---------+
大多数行 b1
与具有相同 item_id
但更大 bid_price
.
的某些行 b2
匹配
在最后六行中,出价 b1
没有其他出价更高 bid_price
,因此这六个是每个 item_id
中最高的出价。这些就是您想要的结果。
一种简单的过滤方法是使用您看到的 WHERE 子句:
WHERE b2.item_id IS NULL
实际上,您可以使用 b2
中已知为非 NULL 的任何列,因为这意味着它为 NULL 的唯一方法是由于 LEFT OUTER JOIN 而没有匹配项。
下面是对正在发生的事情的快速细分:
让我们从联接本身开始。 LEFT JOIN
表示它将获取左侧 (b1) 的所有结果以及右侧 (b2) 的任何相应结果(如果存在)。否则,b2 中的所有列都将为空(请记住这一点,因为它在此查询的工作方式中起着重要作用)。
接下来,它加入 item_id
,因此它只获取该特定项目的价格。然后,它有另一个连接条件,b1.bid_price < b2.bid_price
。任何与 NULL
的比较最终都会被评估为 false。请记住,必须满足这两个条件,否则 b2
中的所有行都为空,并且 b2
代表 bets
table 中的每个条目.这意味着如果 b2
为空,则它要么是该项目的唯一赌注(因为 b1.item_id = b2.item_id
约束),要么是最高的(因为 b1.bid_price < b2.bid_price
约束)。
最后,WHERE
子句。如上所述,JOIN
子句设置完美,因此最高出价将在 b2
中具有 NULL
个值。这使得这部分变得简单,因为现在 WHERE
子句可以简单地获取连接的 b2
具有 NULL
值的每个实例。
我的一个朋友提出了以下查询来查找获胜投注
SELECT b1.*
FROM bids as b1
LEFT JOIN bids AS b2 ON b1.item_id = b2.item_id AND b1.bid_price < b2.bid_price
WHERE b2.item_id IS NULL
它似乎工作正常,但我不明白它是如何工作的,也不知道它是偶然的还是结果总是一样。有人可以解释一下它是如何工作的,尤其是 b1.bid_price < b2.bid_price
如何与明显不存在的 b2.bid_price 一起工作吗?
这是转储:
CREATE TABLE `bids` (
`bid_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`bid_price` decimal(10,2) unsigned NOT NULL,
`user_id` int(11) unsigned NOT NULL,
`item_id` int(11) unsigned NOT NULL,
`bid_date_created` datetime NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`bid_id`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8mb4
INSERT INTO bids VALUES (1, 14000.33, 12, 1, '2021-10-27 19:07:21');
INSERT INTO bids VALUES (2, 13000.60, 6, 1, '2021-10-27 18:07:21');
INSERT INTO bids VALUES (3, 21000.00, 7, 4, '2021-10-29 18:07:21');
INSERT INTO bids VALUES (4, 17000.25, 6, 4, '2021-10-27 18:07:21');
INSERT INTO bids VALUES (6, 5500.00, 6, 7, '2021-11-21 11:46:17');
INSERT INTO bids VALUES (7, 1000.00, 6, 29, '2021-11-22 11:21:41');
INSERT INTO bids VALUES (8, 18000.00, 6, 1, '2021-11-23 11:21:11');
INSERT INTO bids VALUES (9, 110.00, 14, 30, '2021-11-28 15:24:56');
INSERT INTO bids VALUES (10, 120.00, 13, 30, '2021-11-28 15:25:11');
INSERT INTO bids VALUES (11, 159.00, 14, 30, '2021-11-28 15:25:19');
INSERT INTO bids VALUES (12, 170.00, 13, 30, '2021-11-28 15:25:34');
INSERT INTO bids VALUES (13, 200.00, 14, 30, '2021-11-28 15:25:57');
INSERT INTO bids VALUES (14, 250.00, 13, 30, '2021-11-28 15:26:02');
INSERT INTO bids VALUES (15, 6000.00, 14, 6, '2021-11-28 15:26:30');
INSERT INTO bids VALUES (16, 7300.00, 13, 6, '2021-11-28 15:26:44');
INSERT INTO bids VALUES (17, 10000.00, 14, 6, '2021-11-28 15:29:14');
查询使用 LEFT OUTER JOIN 来 try 来查找匹配 item_id
与 b1
相同的行 b2
,但是bid_price
大于 b1
.
左外连接的工作方式是,如果没有匹配项,则无论如何都会返回左侧 table (b1
) 的列,而 b2
的列是空的。如果我们在没有 WHERE 子句的情况下测试查询,您可以在示例数据中看到这一点。
mysql> SELECT b1.bid_id, b1.item_id, b2.bid_id, b2.item_id
FROM bids as b1 LEFT JOIN bids AS b2 ON b1.item_id = b2.item_id
AND b1.bid_price < b2.bid_price;
+--------+---------+--------+---------+
| bid_id | item_id | bid_id | item_id |
+--------+---------+--------+---------+
| 2 | 1 | 1 | 1 |
| 4 | 4 | 3 | 4 |
| 1 | 1 | 8 | 1 |
| 2 | 1 | 8 | 1 |
| 9 | 30 | 10 | 30 |
| 9 | 30 | 11 | 30 |
| 10 | 30 | 11 | 30 |
| 9 | 30 | 12 | 30 |
| 10 | 30 | 12 | 30 |
| 11 | 30 | 12 | 30 |
| 9 | 30 | 13 | 30 |
| 10 | 30 | 13 | 30 |
| 11 | 30 | 13 | 30 |
| 12 | 30 | 13 | 30 |
| 9 | 30 | 14 | 30 |
| 10 | 30 | 14 | 30 |
| 11 | 30 | 14 | 30 |
| 12 | 30 | 14 | 30 |
| 13 | 30 | 14 | 30 |
| 15 | 6 | 16 | 6 |
| 15 | 6 | 17 | 6 |
| 16 | 6 | 17 | 6 |
| 3 | 4 | NULL | NULL |
| 6 | 7 | NULL | NULL |
| 7 | 29 | NULL | NULL |
| 8 | 1 | NULL | NULL |
| 14 | 30 | NULL | NULL |
| 17 | 6 | NULL | NULL |
+--------+---------+--------+---------+
大多数行 b1
与具有相同 item_id
但更大 bid_price
.
b2
匹配
在最后六行中,出价 b1
没有其他出价更高 bid_price
,因此这六个是每个 item_id
中最高的出价。这些就是您想要的结果。
一种简单的过滤方法是使用您看到的 WHERE 子句:
WHERE b2.item_id IS NULL
实际上,您可以使用 b2
中已知为非 NULL 的任何列,因为这意味着它为 NULL 的唯一方法是由于 LEFT OUTER JOIN 而没有匹配项。
下面是对正在发生的事情的快速细分:
让我们从联接本身开始。 LEFT JOIN
表示它将获取左侧 (b1) 的所有结果以及右侧 (b2) 的任何相应结果(如果存在)。否则,b2 中的所有列都将为空(请记住这一点,因为它在此查询的工作方式中起着重要作用)。
接下来,它加入 item_id
,因此它只获取该特定项目的价格。然后,它有另一个连接条件,b1.bid_price < b2.bid_price
。任何与 NULL
的比较最终都会被评估为 false。请记住,必须满足这两个条件,否则 b2
中的所有行都为空,并且 b2
代表 bets
table 中的每个条目.这意味着如果 b2
为空,则它要么是该项目的唯一赌注(因为 b1.item_id = b2.item_id
约束),要么是最高的(因为 b1.bid_price < b2.bid_price
约束)。
最后,WHERE
子句。如上所述,JOIN
子句设置完美,因此最高出价将在 b2
中具有 NULL
个值。这使得这部分变得简单,因为现在 WHERE
子句可以简单地获取连接的 b2
具有 NULL
值的每个实例。