在每个单独月份内按主要客户排名-

时间:2018-11-19 02:37:30

标签: sql-server

我无法按月对主要客户进行排名。我创建了一个新的排名列-但是如何按月将其分解?任何帮助请。下面的代码和表:

排名的逻辑是从表中选择每月排名前两名的客户。还包装在代码中(至少要尝试)是重命名日期字段并将其设置为仅反映月末日期。

 SELECT * FROM table1;
UPDATE table1
SET DATE=EOMONTH(DATE) AS MO_END;
ALTER TABLE table1
ADD COLUMN RANK INT AFTER SALES;
UPDATE table1
SET RANK=
RANK() OVER(PARTITION BY cust ORDER BY sales DESC);
LIMIT 2

从头开始

------+----------+-------+--+
| CUST |   DATE   | SALES |  |
+------+----------+-------+--+
|   36 | 3-5-2018 |    50 |  |
|   37 | 3-15-18  |   100 |  |
|   38 | 3-25-18  |    65 |  |
|   37 | 4-5-18   |    95 |  |
|   39 | 4-21-18  |   500 |  |
|   40 | 4-45-18  |   199 |  |
+------+----------+-------+--+

所需的最终结果

+------+---------+-------+------+--+
| CUST | MO_END  | SALES | RANK |  |
+------+---------+-------+------+--+
|   37 | 3-31-18 |   100 |    1 |  |
|   38 | 3-25-18 |    65 |    2 |  |
|   39 | 4-30-18 |   500 |    1 |  |
|   40 | 4-45-18 |   199 |    2 |  |
+------+---------+-------+------+--+

1 个答案:

答案 0 :(得分:0)

作为简单选择:

select * 
from   (
    select
          table1.*
        , DENSE_RANK() OVER(PARTITION BY cust, EOMONTH(DATE) ORDER BY sales DESC) as ranking
    from table1
    )
where ranking < 3
;

如果存储很重要:我不会使用[rank]作为列名,因为我会避免在SQL中使用任何单词,例如[sales_rank]或类似的词。

with cte as (
    select
          cust
        , DENSE_RANK() OVER(PARTITION BY cust, EOMONTH(DATE) ORDER BY sales DESC) as ranking
    from table1
    )
update cte
set sales_rank = ranking
where ranking < 3
;

实际上没有理由存储月底,只需在over()子句的分区内使用该函数即可。

LIMIT 2并不是可以在SQL Server中使用的东西,并且肯定不能“按组”使用。使用rank()dense_rank()之类的“窗口函数”时,可以在下一个“层”的where子句中使用它们的输出。即在子查询(或cte)中使用这些函数,然后使用where子句按计算出的值过滤行。

还要注意,我使用dense_rank()来确保不跳过任何等级编号,以使后续的where子句生效。