按问题分组

时间:2010-09-26 21:48:32

标签: sql greatest-n-per-group

SQL group by problem

我有问题的SQL组。我的表格如下:

Cust_id.  Price_id     Price. 
----------------------------  
1.          556.        5000. 
-----------------------------  
2.          654.         600. 
2.          432.         487. 
2.          546.         500. 
---------------------------  
3.          455.         200. 
3.          877.         143. 
3.          123.         879. 

现在,当我运行此查询时:

Select  cust_id,  max(price) as max, min(price) as min. 
From table. 
Group by cust_id. 

我明白了。

Cust_id.      Max.        Min. 
1.           5000.       5000. 
2.            600.        487. 
3.            879.        143. 

但我真正想要的不是最高和最低价格,而是与价格相关的price_id 所以结果会是。

Cust_id.       Max.        Min.   
1.             556.        556.   
2.             654.        432.   
3.             123.        877.    

我对如何做到这一点感到茫然。我认为上面的查询将是某种子查询,但就我而言。

4 个答案:

答案 0 :(得分:4)

使用:

   SELECT x.cust_id,
          y.price_id AS max,
          z.price_id AS min
     FROM (SELECT t.cust_id,  
                  MAX(t.price) as max, 
                  MIN(t.price) as min
             FROM TABLE t
         GROUP BY t.cust_id) x
LEFT JOIN TABLE y ON y.cust_id = x.cust_id
                 AND y.price = x.max
LEFT JOIN TABLE z ON z.cust_id = x.cust_id
                 AND z.price = x.min

问题在于,如果cust_id有两个具有相同高(或低)价格的记录,您将看到重复,并且需要提供处理关系的逻辑。

答案 1 :(得分:0)

对于具有排名/分析功能的引擎,应该这样做:

SELECT Pmin.Cust_id, Pmax.Price_id Price_max_id, Pmin.Price_id Price_min_id FROM
(SELECT t.*, ROW_NUMBER() OVER (PARTITION BY t.Cust_id ORDER BY t.Price DESC) ix FROM @table t) Pmin
JOIN (SELECT t.*, ROW_NUMBER() OVER (PARTITION BY t.Cust_id ORDER BY t.Price ASC) ix FROM @table t) Pmax
    ON Pmin.Cust_id = Pmax.Cust_id
WHERE (Pmin.ix = 1) AND (Pmax.ix = 1)

答案 2 :(得分:0)

这是大多数使用MySQL的人都使用GROUP BY的典型问题。 MySQL允许在标准SQL和大多数其他品牌的数据库中不允许的查询。

您需要的是完整行,包括您正在分组的cust_id以外的列,以便该行具有该组中的最高(或最低)价格。你无法从GROUP BY那里得到它。

  

我真正想要的是...... price_id与价格相关联。

但是你想要哪个price_id,最高价格的那一行,还是最低价格的行?这些可能是不同的行。

Cust_id.  Price_id     Price
----------------------------
2.          654          600  <-- max price, price_id 654
2.          432          487  <-- min price, price_id 432
2.          546          500

如果多行价格相同但price_id不同,该怎么办?它应该返回654还是546?

Cust_id.  Price_id     Price
----------------------------
2.          654          600  <-- max price, price_id 654
2.          432          487
2.          546          600  <-- max price, price_id 546

相反,如果你想要max_和最小价格的price_id,你想要的是两行:行没有其他行存在相同的cust_id和更高的价格,行没有其他行存在使用相同的cust_id和更低的价格。

SELECT tmax.cust_id, tmax.price_id, tmax.price, tmin.price_id, tmin.price
FROM table tmax
JOIN table tmin ON tmax.cust_id = tmin.cust_id
WHERE NOT EXISTS (SELECT * FROM table t1 WHERE t1.cust_id = tmax.cust_id AND t1.price > tmax.price) 
  AND NOT EXISTS (SELECT * FROM table t2 WHERE t2.cust_id = tmin.cust_id AND t2.price > tmin.price) 

答案 3 :(得分:0)

这是SQL Server方法

with Data as 
(
    select 1 Cust_id, 556 Price_id,  5000  Price union ALL
    select 2,          654,          600 union ALL
    select 2,          432,          487 union ALL
    select 2,          546,          500 union ALL
    select 3,          455,           200 union ALL
    select 3,          877,           143 union ALL
    select 3,          123,           879
),
Prices as
(
    select Cust_id, MAX(Price) MaxP, MIN(Price) MinP
    from Data
    group by Cust_id
)
select Prices.Cust_id
        ,Data.Price MaxPrice
        , d2.Price MinPrice
from Prices
inner join Data  on Data.Cust_id = Prices.Cust_id and Data.Price = Prices.MaxP
inner join Data d2 on d2.Cust_id = d2.Cust_id and d2.Price = Prices.MinP