【问题标题】:How to rank a column within a group ordered by a date column in SQL Server如何在 SQL Server 中按日期列排序的组中对列进行排名
【发布时间】:2021-01-03 16:25:42
【问题描述】:

我有以下示例数据:

car_id  owner_id    service_date
1        user2  2016-01-02 00:00:00
1        user2  2016-03-02 00:00:00
1        user3  2016-11-02 00:00:00
1        user4  2017-01-02 00:00:00
1        user4  2017-02-12 00:00:00
1        user1  2017-03-22 00:00:00
1        user2  2017-03-24 00:00:00

我正在尝试在sql-server 中为给定的car_idowner_id 列进行排名。

对于给定的car_id 值,如果 'owner_id' 值与前一行中的 'owner_id' 值不同,则排名列应增加 1,其中行按 service_date 升序排序。

预期输出:

car_id  owner_id    service_date    rnk
1        user2  2016-01-02 00:00:00 1
1        user2  2016-03-02 00:00:00 1
1        user3  2016-11-02 00:00:00 2
1        user4  2017-01-02 00:00:00 3
1        user4  2017-02-12 00:00:00 3
1        user1  2017-03-22 00:00:00 4
1        user2  2017-03-24 00:00:00 5

我试图通过划分 car_id 和 owner_id 来使用 dense_rank() 函数找到排名。但它会导致错误的排名。

CREATE TABLE #tb_example (
    car_id INT,
    owner_id NVARCHAR(5),
    service_date SMALLDATETIME
);

INSERT INTO #tb_example (car_id, owner_id, service_date) VALUES (1, 'user2', '2016-01-02');
INSERT INTO #tb_example (car_id, owner_id, service_date) VALUES (1, 'user2', '2016-03-02');
INSERT INTO #tb_example (car_id, owner_id, service_date) VALUES (1, 'user3', '2016-11-02');
INSERT INTO #tb_example (car_id, owner_id, service_date) VALUES (1, 'user4', '2017-01-02');
INSERT INTO #tb_example (car_id, owner_id, service_date) VALUES (1, 'user4', '2017-02-12');
INSERT INTO #tb_example (car_id, owner_id, service_date) VALUES (1, 'user1', '2017-03-22');
INSERT INTO #tb_example (car_id, owner_id, service_date) VALUES (1, 'user2', '2017-03-24');

SELECT *, 
        DENSE_RANK() OVER (PARTITION BY car_id, owner_id ORDER BY service_date) AS rnk 
FROM #tb_example
ORDER BY service_date;

【问题讨论】:

  • 你没有使用DENSE_RANK,你使用了RANK

标签: sql-server tsql


【解决方案1】:

试试这个:

;WITH CTE AS
(
    SELECT *,           
            CASE 
              WHEN owner_id <> COALESCE(LAG(owner_id) OVER 
                                  (PARTITION BY car_id ORDER BY service_date), owner_id) 
                     THEN 1
              ELSE 0 
            END AS grp
    FROM #tb_example
)
SELECT *,
       SUM(grp) OVER (PARTITION BY car_id ORDER BY service_date) + 1 AS rnk
FROM cte 
ORDER BY service_date;

Demo here

查询使用LAG 检测同一car_id 分区内owner_id 的更改,顺序由servic_date 定义。

使用grp 字段,我们使用SUM(grp) OVER .. 将排名计算为变化的总和。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-08
    • 2020-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-06
    • 1970-01-01
    • 2019-11-21
    相关资源
    最近更新 更多