如何为每个类别选择前n条记录

时间:2018-08-09 15:05:25

标签: sql inner-join ssms row-number derived-table

我正在尝试编写一个查询,该查询将连接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 

我希望得到以下结果:

enter image description here

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

3 个答案:

答案 0 :(得分:2)

未经测试,但我会尝试以下方法:

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通常会使查询更具可读性。顺便说一句:我将避免为列指定名称“日期”(保留字),并且我将始终对列使用合格名称。也许使用分析函数等级或密集等级会更合适,但row_number也应该起作用。

答案 1 :(得分:1)

计算/实现子查询后,需要对子查询外部的行号进行过滤。我想这就是你想要的:

@pyqtSlot()
def on_actionTest_triggered(self):
    PatDataLoader.load("TEST","testfile.txt")

请注意,我们在子查询中执行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; 聚合,在此我们还计算了行号。

答案 2 :(得分:0)

我想你想要这个:

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()合并到一个子查询中;聚合优先。)
  • 交易数量由员工公司汇总。
  • 当您有多个表时,请限定所有列名。
  • 您的查询还有很多其他错误,例如表别名放置错误和缺少某些行。