SQL 仅在第一场比赛中加入
SQL Joining on first match only
我正在尝试编写一个 SQL 语句,该语句使用 INNER JOIN
来相互匹配出价和报价。
我有一个出价 table,如下所示
+-------------------------+-------------------+--------------------------------+--------------------------------+
| bid_id | user_id | bid_volume | bid_price |
+-------------------------+-------------------+--------------------------------+--------------------------------+
| 101 | 1 | 100.0000 | 300.0000 |
| 102 | 2 | 200.0000 | 20.0000 |
| 103 | 3 | 50.0000 | 40.0000 |
| 104 | 4 | 60.0000 | 100.0000 |
| 105 | 5 | 75.0000 | 90.0000 |
+-------------------------+-------------------+--------------------------------+--------------------------------+
我有一个报价 table 如下所示
+---------------------------+-------------------+----------------------------------+----------------------------------+
| offer_id | user_id | offer_volume | offer_price |
+---------------------------+-------------------+----------------------------------+----------------------------------+
| 91 | 6 | 60.0000 | 100.0000 |
| 92 | 7 | 75.0000 | 85.0000 |
| 93 | 8 | 100.0000 | 200.0000 |
| 94 | 9 | 75.0000 | 1000.0000 |
| 95 | 10 | 100.0000 | 300.0000 |
+---------------------------+-------------------+----------------------------------+----------------------------------+
我正在尝试匹配出价和出价,应该是一对一的关系,即只有一个出价可以与一个出价匹配。如果有两方或多方出价,则最高出价也应该是获胜者。
如果 bid_volume
与 offer_volume
、bid_price >= offer_price
匹配并且它是所有出价中最高的 bid_price
,则该出价应该是中标。
我按 bid_price
从高到低对出价进行排序,因此首先处理最高出价。当一个出价匹配多个出价时,就会出现问题。
取出价101
以上的数据将满足出价93
和95
。它实际上应该只与报价 93
匹配,因为它是较低的价格。
下面是我的 SQL 的开始,但它限制了我真正坚持的比赛,所以出价与报价是一对一的关系。
SELECT
Bids.user_id AS bidder_user_id,
Offers.user_id AS dealer_user_id,
Bids.bid_volume,
Offers.offer_volume,
Bids.bid_price,
Offers.offer_price
FROM
Bids
INNER JOIN
Offers
ON
/* Volume - Volume must be equal*/
Bids.bid_volume =
Offers.offer_volume AND
/* Price - Bid price greater than or equal to offer price*/
Bids.bid_price >=
Offers.offer_price
ORDER BY
bid_price DESC;
上面的输出如下所示(注意有两个匹配 bidder_user_id = 1
试图只得到一个)
+----------------+----------------+------------+--------------+-----------+-------------+
| bidder_user_id | dealer_user_id | bid_volume | offer_volume | bid_price | offer_price |
+----------------+----------------+------------+--------------+-----------+-------------+
| 1 | 8 | 100.0000 | 100.0000 | 300.0000 | 200.0000 |
| 1 | 10 | 100.0000 | 100.0000 | 300.0000 | 300.0000 |
| 4 | 6 | 60.0000 | 60.0000 | 100.0000 | 100.0000 |
| 5 | 7 | 75.0000 | 75.0000 | 90.0000 | 85.0000 |
+----------------+----------------+------------+--------------+-----------+-------------+
所需的输出如下所示,因此用户 1
出价与两个出价不匹配,但我不确定如何将内部连接限制为仅在第一次出现时匹配。
+----------------+----------------+------------+--------------+-----------+-------------+
| bidder_user_id | dealer_user_id | bid_volume | offer_volume | bid_price | offer_price |
+----------------+----------------+------------+--------------+-----------+-------------+
| 1 | 8 | 100.0000 | 100.0000 | 300.0000 | 200.0000 |
| 4 | 6 | 60.0000 | 60.0000 | 100.0000 | 100.0000 |
| 5 | 7 | 75.0000 | 75.0000 | 90.0000 | 85.0000 |
+----------------+----------------+------------+--------------+-----------+-------------+
Is this how you did it?
SELECT
Bids.user_id AS bidder_user_id,
Offers.user_id AS dealer_user_id,
Bids.bid_volume,
Offers.offer_volume,
Bids.bid_price,
Offers.offer_price,
COUNT(Bids.user_id)
FROM
Bids
INNER JOIN
Offers
ON
/* Volume - Volume must be equal*/
Bids.bid_volume =
Offers.offer_volume AND
/* Price - Bid price greater than or equal to offer price*/
Bids.bid_price >=
Offers.offer_price
ORDER BY
bid_price DESC
GROUP BY
Bids.user_id;
如果你的MySql版本是8.0+你可以在tableOffers
中使用ROW_NUMBER()
window函数得到最低的行offer_price
每个 offer_volume
然后加入 Bids
:
SELECT
b.user_id AS bidder_user_id,
o.user_id AS dealer_user_id,
b.bid_volume,
o.offer_volume,
b.bid_price,
o.offer_price
FROM Bids b
INNER JOIN (
SELECT *, ROW_NUMBER() OVER (PARTITION BY offer_volume ORDER BY offer_price) rn
FROM Offers
) o
ON b.bid_volume = o.offer_volume AND b.bid_price >= o.offer_price
WHERE o.rn = 1
ORDER BY b.bid_price DESC;
对于以前的版本,您可以使用 NOT EXISTS
:
SELECT
b.user_id AS bidder_user_id,
o.user_id AS dealer_user_id,
b.bid_volume,
o.offer_volume,
b.bid_price,
o.offer_price
FROM Bids b
INNER JOIN (
SELECT o1.* FROM Offers o1
WHERE NOT EXISTS (
SELECT 1 FROM Offers o2
WHERE o2.offer_volume = o1.offer_volume AND o2.offer_price < o1.offer_price
)
) o
ON b.bid_volume = o.offer_volume AND b.bid_price >= o.offer_price
ORDER BY b.bid_price DESC;
参见demo。
我正在尝试编写一个 SQL 语句,该语句使用 INNER JOIN
来相互匹配出价和报价。
我有一个出价 table,如下所示
+-------------------------+-------------------+--------------------------------+--------------------------------+
| bid_id | user_id | bid_volume | bid_price |
+-------------------------+-------------------+--------------------------------+--------------------------------+
| 101 | 1 | 100.0000 | 300.0000 |
| 102 | 2 | 200.0000 | 20.0000 |
| 103 | 3 | 50.0000 | 40.0000 |
| 104 | 4 | 60.0000 | 100.0000 |
| 105 | 5 | 75.0000 | 90.0000 |
+-------------------------+-------------------+--------------------------------+--------------------------------+
我有一个报价 table 如下所示
+---------------------------+-------------------+----------------------------------+----------------------------------+
| offer_id | user_id | offer_volume | offer_price |
+---------------------------+-------------------+----------------------------------+----------------------------------+
| 91 | 6 | 60.0000 | 100.0000 |
| 92 | 7 | 75.0000 | 85.0000 |
| 93 | 8 | 100.0000 | 200.0000 |
| 94 | 9 | 75.0000 | 1000.0000 |
| 95 | 10 | 100.0000 | 300.0000 |
+---------------------------+-------------------+----------------------------------+----------------------------------+
我正在尝试匹配出价和出价,应该是一对一的关系,即只有一个出价可以与一个出价匹配。如果有两方或多方出价,则最高出价也应该是获胜者。
如果 bid_volume
与 offer_volume
、bid_price >= offer_price
匹配并且它是所有出价中最高的 bid_price
,则该出价应该是中标。
我按 bid_price
从高到低对出价进行排序,因此首先处理最高出价。当一个出价匹配多个出价时,就会出现问题。
取出价101
以上的数据将满足出价93
和95
。它实际上应该只与报价 93
匹配,因为它是较低的价格。
下面是我的 SQL 的开始,但它限制了我真正坚持的比赛,所以出价与报价是一对一的关系。
SELECT
Bids.user_id AS bidder_user_id,
Offers.user_id AS dealer_user_id,
Bids.bid_volume,
Offers.offer_volume,
Bids.bid_price,
Offers.offer_price
FROM
Bids
INNER JOIN
Offers
ON
/* Volume - Volume must be equal*/
Bids.bid_volume =
Offers.offer_volume AND
/* Price - Bid price greater than or equal to offer price*/
Bids.bid_price >=
Offers.offer_price
ORDER BY
bid_price DESC;
上面的输出如下所示(注意有两个匹配 bidder_user_id = 1
试图只得到一个)
+----------------+----------------+------------+--------------+-----------+-------------+
| bidder_user_id | dealer_user_id | bid_volume | offer_volume | bid_price | offer_price |
+----------------+----------------+------------+--------------+-----------+-------------+
| 1 | 8 | 100.0000 | 100.0000 | 300.0000 | 200.0000 |
| 1 | 10 | 100.0000 | 100.0000 | 300.0000 | 300.0000 |
| 4 | 6 | 60.0000 | 60.0000 | 100.0000 | 100.0000 |
| 5 | 7 | 75.0000 | 75.0000 | 90.0000 | 85.0000 |
+----------------+----------------+------------+--------------+-----------+-------------+
所需的输出如下所示,因此用户 1
出价与两个出价不匹配,但我不确定如何将内部连接限制为仅在第一次出现时匹配。
+----------------+----------------+------------+--------------+-----------+-------------+
| bidder_user_id | dealer_user_id | bid_volume | offer_volume | bid_price | offer_price |
+----------------+----------------+------------+--------------+-----------+-------------+
| 1 | 8 | 100.0000 | 100.0000 | 300.0000 | 200.0000 |
| 4 | 6 | 60.0000 | 60.0000 | 100.0000 | 100.0000 |
| 5 | 7 | 75.0000 | 75.0000 | 90.0000 | 85.0000 |
+----------------+----------------+------------+--------------+-----------+-------------+
Is this how you did it?
SELECT
Bids.user_id AS bidder_user_id,
Offers.user_id AS dealer_user_id,
Bids.bid_volume,
Offers.offer_volume,
Bids.bid_price,
Offers.offer_price,
COUNT(Bids.user_id)
FROM
Bids
INNER JOIN
Offers
ON
/* Volume - Volume must be equal*/
Bids.bid_volume =
Offers.offer_volume AND
/* Price - Bid price greater than or equal to offer price*/
Bids.bid_price >=
Offers.offer_price
ORDER BY
bid_price DESC
GROUP BY
Bids.user_id;
如果你的MySql版本是8.0+你可以在tableOffers
中使用ROW_NUMBER()
window函数得到最低的行offer_price
每个 offer_volume
然后加入 Bids
:
SELECT
b.user_id AS bidder_user_id,
o.user_id AS dealer_user_id,
b.bid_volume,
o.offer_volume,
b.bid_price,
o.offer_price
FROM Bids b
INNER JOIN (
SELECT *, ROW_NUMBER() OVER (PARTITION BY offer_volume ORDER BY offer_price) rn
FROM Offers
) o
ON b.bid_volume = o.offer_volume AND b.bid_price >= o.offer_price
WHERE o.rn = 1
ORDER BY b.bid_price DESC;
对于以前的版本,您可以使用 NOT EXISTS
:
SELECT
b.user_id AS bidder_user_id,
o.user_id AS dealer_user_id,
b.bid_volume,
o.offer_volume,
b.bid_price,
o.offer_price
FROM Bids b
INNER JOIN (
SELECT o1.* FROM Offers o1
WHERE NOT EXISTS (
SELECT 1 FROM Offers o2
WHERE o2.offer_volume = o1.offer_volume AND o2.offer_price < o1.offer_price
)
) o
ON b.bid_volume = o.offer_volume AND b.bid_price >= o.offer_price
ORDER BY b.bid_price DESC;
参见demo。