我有一个商店列表,商店内的部门和每个部门的销售情况,如此(使用子查询中的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时,它都会包含子查询中的所有列表。没有临时表,有没有一个很好的干净方法呢?
答案 0 :(得分: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;
答案 1 :(得分:2)
这适用于Oracle,其他实现可能具有不同的分析函数语法(或完全缺少它们):
select store
, max(department) keep(dense_rank last order by sales)
, max(sales)
from (
...query that generates your results...
)
group by store
答案 2 :(得分:2)
我的2个SQL 2005解决方案如下。如果两个销售数字相同,我目前可以看到的其他数据可能无法返回正确的数据。这取决于你的需求。
第一个使用Row_Number()函数,所有行都从最低销售额到最高销售额排序(然后是一些打破平局规则)。然后每个商店选择最高等级以获得结果。
您可以尝试将Partion By子句添加到Row_Number函数(请参阅BOL)和/或使用内部联接而不是“in”子句进行调查。
第二,借用Turnkey的想法,再次对它们进行排名,但按商店分区,因此我们可以选择排名第一的。 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
答案 3 :(得分: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个部门,因此前1和[您的关系标准]可以区分它们。
答案 4 :(得分: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
答案 5 :(得分: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
WHERE“Sales”=您的原始查询
答案 6 :(得分:0)
这将有效
Select Store, Department, Sales
From yourTable A
Where Sales = (Select Max(Sales)
From YourTable
Where Store = A.Store)