MySQL INNER JOIN查找行组的最大值

时间:2012-12-29 19:37:51

标签: mysql inner-join max

我已经提出了我正在尝试做的事情的样本

http://sqlfiddle.com/#!2/514d2/2

此演示会查找“出价”表格中不是每个listing_id出价最高的所有行。我需要做的是查找所有列表,其中$ userid(在这种情况下是用户1)是出价最高者。

有人可以帮我解决这个问题吗?

对于那些不使用SQLFiddle的人......

  • 表名:列表
  • 表名:出价

SQL:

SELECT listings.end_date, 
    listings.user_id, 
    listings.title, 
    listings.auc_fp, 
    listings.id, 
    listings.auc_image1 
FROM listings 
INNER JOIN 
    (SELECT 
     listing_id, 
     user_id, 
     bid maxBid 
 FROM bids 
 WHERE bid 
 NOT IN 
     (SELECT MAX(bid) 
      FROM bids) 
      GROUP BY 
         listing_id, 
         user_id) 
    bids ON 
      listings.id = bids.listing_id 
  WHERE bids.user_id=1 
  AND listings.end_date > NOW() 
  ORDER BY listings.list_ts DESC

此查询成功找到$ userid已设置出价的所有商家信息,但不是最高出价者。我想查找$ userid已经出价的所有商家信息,并且是最高出价者。

2 个答案:

答案 0 :(得分:2)

初步观察

原始查询可以重新格式化,以便于阅读:

SELECT listings.end_date, 
       listings.user_id, 
       listings.title, 
       listings.auc_fp, 
       listings.id, 
       listings.auc_image1 
  FROM listings 
  JOIN (SELECT listing_id, 
               user_id, 
               bid maxBid 
          FROM bids 
         WHERE bid NOT IN (SELECT MAX(bid) FROM bids) 
         GROUP BY listing_id, user_id
       ) AS bids
    ON listings.id = bids.listing_id 
 WHERE bids.user_id = 1 
   AND listings.end_date > NOW() 
 ORDER BY listings.list_ts DESC

我注意到列为maxBid的列不一定是任何商家信息的最高出价。此查询也仅适用于仍处于打开状态的商家信息。我不相信它会产生预期的答案;排除的唯一出价是包含任何商家信息的总出价最高的出价。


TDQD - 测试驱动的查询设计

真正的问题是:

  

查找$ userid(= 1)已设置出价且 出价最高者的所有当前打开的商家信息。

时间做TDQD - 测试驱动的查询设计;我的大脑工作速度不够快,无法一次完成。

每个商家信息的最高出价

SELECT listing_id, MAX(bid) AS maxBid
  FROM bids
 GROUP BY listing_id

查找最高出价的用户为用户1

的商家信息的出价
SELECT b.listing_id
  FROM bids AS b
  JOIN (SELECT listing_id, MAX(bid) AS maxBid
          FROM bids
         GROUP BY listing_id
       ) AS m
    ON m.listing_id = b.listing_id AND m.maxBid = b.bid
 WHERE b.user_id = 1

查找最高出价的用户为用户1

的商家信息
SELECT l.*
  FROM listings AS l
  JOIN (SELECT b.listing_id
          FROM bids AS b
          JOIN (SELECT listing_id, MAX(bid) AS maxBid
                  FROM bids
                 GROUP BY listing_id
               ) AS m
            ON m.listing_id = b.listing_id AND m.maxBid = b.bid
         WHERE b.user_id = 1
       ) AS u
    ON l.id = u.listing_id

将查询限制为打开列表

SELECT l.*
  FROM listings AS l
  JOIN (SELECT b.listing_id
          FROM bids AS b
          JOIN (SELECT listing_id, MAX(bid) AS maxBid
                  FROM bids
                 GROUP BY listing_id
               ) AS m
            ON m.listing_id = b.listing_id AND m.maxBid = b.bid
         WHERE b.user_id = 1
       ) AS u
    ON l.id = u.listing_id
 WHERE l.end_date > NOW()

您可以而且应该将*替换为您感兴趣的确切列。如果您需要出价详情,也可以获得这些。


针对Informix进行测试

需要进行一些小的语法更改 - NOW()被CURRENT YEAR TO SECOND取代 - 但这只会影响最后一个查询。 DDL需要更多工作才能将语法转换为更接近DBMS的中性格式; MySQL有一些奇怪的约定。

未来读者请注意:将NOW()CURRENT YEAR TO SECOND替换为2012-12-29 12:37:43等值,以获得相同的结果。数据中的列表将从2013-01-10 00:00:001开始到期。

查询1:

SELECT listing_id, MAX(bid) AS maxBid
  FROM bids
 GROUP BY listing_id;

输出1:

listing_id  maxbid
34          95.37
40          103.00
38          507.00
41          94.00
48          76.00
6469        22.00
6472        5.00
37          511.00
31          100.00

查询2:

SELECT b.listing_id
  FROM bids AS b
  JOIN (SELECT listing_id, MAX(bid) AS maxBid
          FROM bids
         GROUP BY listing_id
       ) AS m
    ON m.listing_id = b.listing_id AND m.maxBid = b.bid
 WHERE b.user_id = 1;

输出2:

listing_id
34
37
48
6469
6472

查询3:

SELECT l.end_date, l.user_id, l.title, l.id
  FROM listings AS l
  JOIN (SELECT b.listing_id
          FROM bids AS b
          JOIN (SELECT listing_id, MAX(bid) AS maxBid
                  FROM bids
                 GROUP BY listing_id
               ) AS m
            ON m.listing_id = b.listing_id AND m.maxBid = b.bid
         WHERE b.user_id = 1
       ) AS u
    ON l.id = u.listing_id;

输出3:     end_date user_id标题ID     2013-01-09 08:11:16 1圣诞树6469     2013-01-11 09:17:31 3另一个测试项目6472

查询4

SELECT l.end_date, l.user_id, l.title, l.id
  FROM listings AS l
  JOIN (SELECT b.listing_id
          FROM bids AS b
          JOIN (SELECT listing_id, MAX(bid) AS maxBid
                  FROM bids
                 GROUP BY listing_id
               ) AS m
            ON m.listing_id = b.listing_id AND m.maxBid = b.bid
         WHERE b.user_id = 1
       ) AS u
    ON l.id = u.listing_id
 WHERE l.end_date > CURRENT YEAR TO SECOND;

输出4:

end_date                user_id     title                   id
2013-01-09 08:11:16     1           Christmas Tree          6469
2013-01-11 09:17:31     3           Another test item       6472

答案 1 :(得分:1)

这应该使用左连接来执行您需要的操作,以确保每个产品没有更好的出价;

SELECT DISTINCT listings.end_date, listings.user_id, listings.title, 
       listings.auc_fp, listings.id, listings.auc_image1
FROM listings 
JOIN bids b1 
  ON b1.listing_id=listings.id 
LEFT JOIN bids b2 
  ON b2.listing_id=listings.id AND b1.bid < b2.bid
WHERE b1.user_id = 1
  AND b2.bid IS NULL
  AND listings.end_date > NOW()

An SQLfiddle based on the original to test with