Макс Суммы в SQL - PullRequest
       28

Макс Суммы в SQL

8 голосов
/ 04 ноября 2008

У меня есть список магазинов, отделов внутри магазинов и продаж для каждого отдела, например, (созданный с использованием max (sales) в подзапросе, но это не очень важно, я не думаю, что)

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, он включает в себя все списки из моего подзапроса. Есть ли хороший чистый способ сделать это без временной таблицы?

Ответы [ 7 ]

4 голосов
/ 04 ноября 2008

Это работает в 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;
2 голосов
/ 04 ноября 2008

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

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

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

Второй, заимствуя идею «под ключ», снова ранжирует их, но разделяет по магазинам, поэтому мы можем выбрать первый ранжированный. Dense_Rank, возможно, даст двум одинаковым строкам одинаковый ранг, поэтому, если store и Department не были уникальными, он мог бы вернуть две строки. С 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
2 голосов
/ 04 ноября 2008

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

select store
     , max(department) keep(dense_rank last order by sales)
     , max(sales)
  from (
        ...query that generates your results...
       )
 group by store
1 голос
/ 04 ноября 2008

Это будет работать в 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 отдел в случае связей, следовательно, первые 1 и [ваши критерии для связей] различают их.

0 голосов
/ 04 ноября 2008

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

Select Store, Department, Sales
From yourTable A
Where Sales = (Select Max(Sales)
               From YourTable
               Where Store = A.Store)
0 голосов
/ 04 ноября 2008

Это будет работать в 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

ГДЕ "Продажи" = ваш оригинальный запрос

0 голосов
/ 04 ноября 2008

Может быть, это может сработать. Хотя не пробовал, могло бы быть лучшее решение ...

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