группировать по проблеме - PullRequest
       4

группировать по проблеме

2 голосов
/ 27 сентября 2010

SQL группа по проблеме

У меня есть 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. 

Но я действительно хочу не максимальную и минимальную цену, а идентификатор цены, связанный с ценой.
Таким образом, результаты будут.

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

Я не знаю, как это сделать.Я думаю, что вышеупомянутый запрос был бы подзапросом некоторого вида, но это насколько я получил.

Ответы [ 4 ]

4 голосов
/ 27 сентября 2010

Использование:

   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 имеет две записи с одинаковой высокой (или низкой) ценой, вы увидите дубликаты и должны будете предоставить логику для работысвязи.

0 голосов
/ 27 сентября 2010

Вот подход 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
0 голосов
/ 27 сентября 2010

Это классическая проблема, с которой сталкивается большинство людей, использующих MySQL, с GROUP BY. MySQL разрешает запросы, которые не разрешены в стандартном SQL и в большинстве других марок баз данных.

Вам нужна полная строка, включая столбцы, отличные от cust_id, по которому вы группируете, чтобы эта строка имела самую высокую (или самую низкую) цену в этой группе. Вы не можете получить это от GROUP BY.

Что я действительно хочу, так это ... 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

Вместо этого, если вы хотите, чтобы 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) 
0 голосов
/ 27 сентября 2010

Это должно сработать для двигателей с функциями ранжирования / анализа:

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)
...