2010-09-26 2 views
2

Группа 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. 

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

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

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

+0

Что DB двигатель вы используете? – Lucero

+1

Какую базу вы используете? (SQL Server, MySQL, PostGRES, ...) – Andomar

+1

@dlb - Не знаете, почему вы вернули мои изменения ... но уродливый вопрос не поможет получить ответы ... –

ответ

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

+0

cuts_id vs cust_id? Вопрос путается ... –

+0

@Jonathan Leffler: Я использовал запрос, предоставленный OP, построив его. –

+0

нуждается в настройке - OP хочет максимальную/минимальную цену price_ids, а не цены. –

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

Использование RANK может возвращать дубликаты; ROW_NUMBER гарантирует, что дубликаты не будут возвращены. –

+0

Да, это было исправление уже до того, как я увидел ваш комментарий. Спасибо хоть. – Lucero

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 

Вместо этого, если вы хотите 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

Вот подход 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

У этого также есть проблема с дубликатами. – Lucero

Смежные вопросы