T-SQL Group By Problem

时间:2011-01-24 03:14:06

标签: sql sql-server tsql group-by aggregate-functions

我遇到了以下问题(或者只是一个思维障碍):

我有一个表(实际上是一个表中的视图),其中包含以下列和数据:

http://i.stack.imgur.com/n98Sw.png

现在,我想通过“Customer”列对此数据进行分组,并获得具有最高“CompetitorCount”的“CompetitorName”。 当然我可以创建这样的查询:

SELECT Customer, MAX(CompetitorCount) FROM MyTable GROUP BY Customer

这将返回两行:

Foo; 12  
Bar; 7

但我无法以这种方式获得竞争对手名称。如果我将其包含在分组中,则“客户”将多次显示。否则我必须使用聚合函数来选择我想要使用的“CompetitorName”,但当然MAX不起作用。

我确信这可以以某种方式完成,但目前我还不知道如何。

提前感谢您的帮助。

2 个答案:

答案 0 :(得分:7)

select customer, competitorname, competitorcount
FROM
(
 select *, rn = ROW_NUMBER() over (
  partition by customer order by competitorcount desc)
 from tbl
) X
WHERE rn=1

如果要以最大值显示TIES,请将ROW_NUMBER()更改为RANK()。

您甚至可能会更快地找到cross apply版本,但它不适用于关系。如果竞争对手之间存在联系,TOP 1可确保单一记录。

select C.*
FROM
(select distinct customer from tbl) A
cross apply
(select top 1 B.*
 from tbl B
 where A.customer = B.customer
 order by B.competitorcount desc) C

首先选择所有不同的客户。然后,对于每个客户,它都会关闭并检索该客户的MAX(竞争对手)记录。

答案 1 :(得分:3)

有几种方法可以做到这一点,但最直接的方法是:

WITH Custs AS (
   SELECT 
      Customer, 
      CompetitorName,
      CompetitorCount,
      ROW_NUMBER() OVER (PARTITION BY Customer ORDER BY CompetitorCount DESC) AS __ROW
   From MyTable
)
SELECT
    Customer,
    CompetitorName,
    CompetitorCount
FROM Custs
WHERE __ROW = 1;

如果您想要关联(最高计数与客户相关,并且您想指定两行),请在上述查询中使用RANK()而不是ROW_NUMBER()

您也可以使用自联接来执行此操作:

WITH Custs AS (
    SELECT Customer, MAX(CompetitorCount) AS CompetitorCount
    FROM MyTable 
    GROUP BY Customer)
SELECT m.Customer, m.CompetitorName, m.CompetitorCount
FROM MyTable m
INNER JOIN Custs c
   ON  c.CompetitorCount = m.CompetitorCount
   AND c.Customer        = m.Customer;