2008-11-04 11 views
8

У меня есть список магазинов, отделов в магазинах и продаж для каждого отдела, например (создается с использованием max (продаж) в подзапросе, но это не очень важно здесь, я не думаю):Макс. Сумма в SQL

toronto baskets 500 
vancouver baskets 350 
halifax baskets 100 
toronto noodles 275 
vancouver noodles 390 
halifax noodles 120 
halifax fish 200 

Я хотел бы попросить самый продаваемый отдел в каждом магазине. Результаты должны выглядеть так:

toronto baskets 500 
vancouver noodles 275 
halifax fish 200 

Всякий раз, когда я использую GROUP BY, он включает все списки из моего подзапроса. Есть ли хороший чистый способ сделать это без временной таблицы?

+0

Какая платформа базы данных? sql-сервер? оракул? – TheSoftwareJedi 2008-11-04 00:12:53

+0

Кто бы мог подумать, что лапша будет настолько популярна в Ванкувере, а? – TheSoftwareJedi 2008-11-04 00:14:03

+0

Это снова «победитель». http://stackoverflow.com/questions/246870/simple-sql-query – 2008-11-04 12:48:16

ответ

2

Это работает в Oracle, другие реализации могут иметь разный синтаксис для аналитических функций (или отсутствие их полностью):

select store 
    , max(department) keep(dense_rank last order by sales) 
    , max(sales) 
    from (
     ...query that generates your results... 
     ) 
group by store 
1

Это будет работать в SQL Server, начиная с 2005 года:

with data as 
(select store, department, sales 
from <your query>), 
maxsales as 
(select store, sales = max(sales) 
from data 
group by store) 
select store, (select top 1 department from data where store = t.store and sales = t.sales order by [your criteria for ties]), sales 
from maxsales m 

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

0

Возможно, это может сработать. Не пробовал хотя, может быть лучшим решением ...

select yourTable.store, dept, sales 
from yourTable 
join (
    select store, max(sales) as maxSales from yourTable group by store 
) tempTable on tempTable.store = yourTable.store 
      and tempTable.maxSales = yourTable.sales 
4

Это работает в Sql Server (2000 и выше точно)

SELECT a.Store, a.Department, a.Sales 
FROM temp a 
INNER JOIN 
(SELECT store, max(sales) as sales 
FROM temp 
GROUP BY Store) b 
ON a.Store = b.Store AND a.Sales = b.Sales; 
0

Это будет работать в SQL Server без температуры столы:

SELECT Store, Department, Sales FROM 
(SELECT Store, Department, Sales, 
DENSE_RANK() OVER (PARTITION BY Store 
ORDER BY Sales DESC) AS Dense_Rank 
FROM Sales) A WHERE Dense_Rank = 1 

ГДЕ "Sales" = исходный запрос

0

Это будет работать

Select Store, Department, Sales 
From yourTable A 
Where Sales = (Select Max(Sales) 
       From YourTable 
       Where Store = A.Store) 
2

Ниже представлены мои 2 решения для SQL 2005. Остальные, которые я вижу до сих пор, могут не возвращать правильные данные, если две цифры продаж одинаковы. Это зависит от ваших потребностей.

Первый использует функцию Row_Number(), все строки ранжируются от самых низких до самых высоких (тогда некоторые правила нарушения связи). Затем для получения результата выбирается самый высокий ранг для каждого магазина.

Вы можете попробовать добавить предложение Partion By к функции Row_Number (см. BOL) и/или исследовать, используя внутреннее соединение вместо предложения «in».

Второе, заимствование по идее «под ключ», снова оценивает их, но разделяет по магазинам, поэтому мы можем выбрать первое место. Dense_Rank, возможно, даст две одинаковые строки одного ранга, поэтому, если хранилище и отдел не были уникальными, он мог бы вернуть две строки. С Row_number число уникально в разделе.

Некоторые вещи, о которых следует помнить, это то, что это может быть медленным, но будет быстрее для большинства наборов данных, чем подзапрос в одном из других решений. В этом решении запрос должен запускаться один раз в строке (включая сортировку и т. Д.), Что может привести к множеству запросов.

Другие запросы: выберите максимальный объем продаж в магазине и верните данные таким образом, возвратите повторяющиеся строки для магазина, если два отдела имеют одинаковые продажи. Последний запрос показывает это.

DECLARE @tbl as TABLE (store varchar(20), department varchar(20), sales int) 

INSERT INTO @tbl VALUES ('Toronto', 'Baskets', 500) 
INSERT INTO @tbl VALUES ('Toronto', 'Noodles', 500) 
INSERT INTO @tbl VALUES ('Toronto', 'Fish', 300) 
INSERT INTO @tbl VALUES ('Halifax', 'Fish', 300) 
INSERT INTO @tbl VALUES ('Halifax', 'Baskets', 200) 

-- Expect Toronto/Noodles/500 and Halifax/Fish/300 

;WITH ranked AS -- Rank the rows by sales from 1 to x 
(
    SELECT 
     ROW_NUMBER() OVER (ORDER BY sales, store, department) as 'rank', 
     store, department, sales 
    FROM @tbl 
) 

SELECT store, department, sales 
FROM ranked 
WHERE rank in (
    SELECT max(rank) -- chose the highest ranked per store 
    FROM ranked 
    GROUP BY store 
) 

-- Another way 
SELECT store, department, sales 
FROM (
    SELECT 
     DENSE_RANK() OVER (PARTITION BY store ORDER BY sales desc, 
store desc, department desc) as 'rank', 
     store, department, sales 
    FROM @tbl 
) tbl 
WHERE rank = 1 


-- This will bring back 2 rows for Toronto 
select tbl.store, department, sales 
from @tbl tbl 
    join (
     select store, max(sales) as maxSales from @tbl group by store 
    ) tempTable on tempTable.store = tbl.store 
      and tempTable.maxSales = tbl.sales