如何在 SQL Server 中按日期列排序的组中对列进行排名

Posted

技术标签:

【中文标题】如何在 SQL Server 中按日期列排序的组中对列进行排名【英文标题】:How to rank a column within a group ordered by a date column in 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 【参考方案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 .. 将排名计算为变化的总和。

【讨论】:

以上是关于如何在 SQL Server 中按日期列排序的组中对列进行排名的主要内容,如果未能解决你的问题,请参考以下文章

对 Spark DataFrame 中第一列的值形成的组中的其他列进行排序

如何在 Pandas 数据框中按行值对日期时间列进行排序?

如何根据日期对SQL Server中的多个列进行排序

如何在 SQL 中按多列分组并按日期排序?

具有共同 id 的组中具有最大天数的两个日期之间的差异

如何在 Oracle 的组中获得第三个 [重复]