如何 Select 每个类别的前 n 条记录

How to Select top n Records for Each Category

我正在尝试编写一个连接 2 个表的查询,它将为我提供前 5 个名称以及他们在特定日期范围(即 01-01-2016 到 12-31 之间的某个位置)销售的商品数量-2017.

根据我一直在研究的内容,这就是我想出的:

SELECT
    EmployeeName, 
    COUNT(ID) AS 'Number of Deals', 
    CompanyNumber
FROM
(
    SELECT
        EmployeeName, 
        DealID, 
        CompanyNumber,
        ROW_NUMBER() OVER (PARTITION BY CompanyNumber ORDER BY DealID) AS rn
    FROM Deal
    JOIN DealEmployee
        ON Deal.DealID. =DealEmployee.DealID AS T
    WHERE
        Deal.Status = 2 AND
        Date BETWEEN '2016-01-01' AND '2017-12-31' AND
        EmployeeName != '' AND T.rn <=5 

我希望得到以下结果:

我是新手,我知道我的语法不正确。提供任何帮助将不胜感激

在calculated/materialized之后,您需要在子查询之外的行号上进行过滤。我想这就是你想要的:

SELECT EmployeeName, CompanyNumber, cnt
FROM
(
    SELECT EmployeeName, CompanyNumber, COUNT(*) AS cnt,
        ROW_NUMBER() OVER (PARTITION BY CompanyNumber ORDER BY COUNT(*) DESC) rn
    FROM Deal d
    INNER JOIN DealEmployee de
        ON d.DealID = de.DealID
    WHERE d.Status = 2 AND Date BETWEEN '2016-01-01' AND '2017-12-31' AND
          EmployeeName != ''
    GROUP BY EmployeeName, CompanyNumber
) t
WHERE rn <= 5
ORDER BY
    CompanyNumber,
    cnt DESC;

请注意,我们在子查询内执行 GROUP BY 聚合,我们还计算行号。

未测试,但我会尝试类似的方法:

with
basedata as (    
select EmployeeName
     , CompanyNumber
     , COUNT(ID) as Number_of_Deals
  from Deal
  join DealEmployee
    on Deal.DealID = DealEmployee.DealID    
 where Deal.Status = 2
   and Date between '2016-01-01' and '2017-12-31'
   and EmployeeName !=''
 group by EmployeeName
        , CompanyNumber 
)
,
basedata_with_rank as (
select t.*
     , row_number() over (partition by CompanyNumber order by Number_of_Deals desc) rn
  from basedata
)
select *
  from basedata_with_rank
 where rn <= 5
 order by CompanyNumber
        , Number_of_Deals desc

使用 CTE 通常可以提高查询的可读性。顺便说一句:我会避免给列命名 "date"(一个保留字),并且我会始终为我的列使用限定名称。也许使用解析函数 rank 或 dense rank 会更合适,但 row_number 也应该有效。

我想你想要这个:

SELECT EmployeeName, num_deals, CompanyNumber
FROM (SELECT EmployeeName, CompanyNumber, COUNT(*) as num_deals,
             ROW_NUMBER() OVER (PARTITION BY CompanyNumber ORDER BY COUNT(*) DESC) AS seqnum
      FROM Deal d JOIN
           DealEmployee de
           ON Deal.DealID. = de.DealID 
      WHERE d.Status = 2 AND
            Date BETWEEN '2016-01-01' AND '2017-12-31' AND
            EmployeeName <> ''
      GROUP BY employee, CompanyNumber
     ) t
WHERE seqnum <= 5;

备注:

  • 您需要在执行 row_number() 之前进行聚合,因为您要根据计数进行枚举。 (此版本将聚合和 row_number() 合并到一个子查询中;聚合在前。)
  • 交易数量按员工公司汇总。
  • 当您有多个 table 时,限定 所有 列名称。
  • 您的查询还有许多其他错误,例如 table 别名放错位置以及缺少某些行。