8

我有一个商店列表、商店中的部门以及每个部门的销售额,就像这样(在子查询中使用 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 时,它都会包含我的子查询中的所有列表。在没有临时表的情况下,有没有一种干净的方法可以做到这一点?

4

7 回答 7

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;
于 2008-11-04T00:45:39.087 回答
2

这在 Oracle 中有效,其他实现可能对分析函数有不同的语法(或完全没有它们):

select store
     , max(department) keep(dense_rank last order by sales)
     , max(sales)
  from (
        ...query that generates your results...
       )
 group by store
于 2008-11-04T00:12:31.167 回答
2

我对 SQL 2005 的 2 个解决方案如下。如果两个销售数据相同,那么到目前为止我可以看到的其他数据可能不会返回正确的数据。不过,这取决于您的需求。

第一个使用 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
于 2008-11-04T12:44:09.197 回答
1

从 2005 年起,这将在 SQL Server 中工作:

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 个和 [您的联系标准] 可以区分它们。

于 2008-11-04T00:42:21.650 回答
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
于 2008-11-04T00:42:39.967 回答
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" = 您的原始查询

于 2008-11-04T01:13:06.817 回答
0

这将起作用

Select Store, Department, Sales
From yourTable A
Where Sales = (Select Max(Sales)
               From YourTable
               Where Store = A.Store)
于 2008-11-04T01:16:17.260 回答