【问题标题】:SQL Joining on first match only仅在第一次匹配时加入 SQL
【发布时间】:2021-03-19 16:36:38
【问题描述】:

我正在尝试编写一个 SQL 语句,它使用 INNER JOIN 来匹配出价和出价。

我有一个如下所示的出价表

+-------------------------+-------------------+--------------------------------+--------------------------------+
| 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 |
+-------------------------+-------------------+--------------------------------+--------------------------------+

我有一个如下所示的报价表

+---------------------------+-------------------+----------------------------------+----------------------------------+
| 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_volumeoffer_volumebid_price >= offer_price 匹配并且它是所有出价中最高的bid_price,则该出价应为中标。

我按bid_price 从高到低排序出价,因此首先处理最高出价。当一个出价匹配多个出价时,就会出现问题。

获取高于出价101 的数据将满足出价9395。它应该只与报价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 |
+----------------+----------------+------------+--------------+-----------+-------------+

【问题讨论】:

    标签: mysql sql inner-join


    【解决方案1】:

    如果您的 MySql 版本是 8.0+,您可以使用表 Offers 中的 ROW_NUMBER() 窗口函数为每个 offer_volume 获取具有最低 offer_price 的行,然后加入到 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

    【讨论】:

      【解决方案2】:

      你是这样做的吗?

      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;
      

      【讨论】:

      • 不走运,我在order by之前添加了group by,这是我得到的Error Code: 1055. Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'Bids.user_id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
      • 不幸的是我仍然遇到同样的错误,这将被包含在一个插入语句中,该语句目前没有额外的列
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-24
      • 1970-01-01
      相关资源
      最近更新 更多