基于多个字段对集合中的记录进行排名

时间:2017-11-07 22:24:19

标签: sql sql-server sql-server-2008 sql-server-2008-r2

╔════════════════════╦═══════════╦══════════╦═══════╦══════╗
║      ENDTIME       ║ TRAILERID ║ POSITION ║ STORE ║ STOP ║
╠════════════════════╬═══════════╬══════════╬═══════╬══════╣
║ 11/7/2017 15:15:44 ║       145 ║ L1       ║ BOS   ║    1 ║
║ 11/7/2017 15:16:57 ║       145 ║ L2       ║ NY    ║    3 ║
║ 11/7/2017 15:17:24 ║       145 ║ R1       ║ NY    ║    2 ║
║ 11/7/2017 15:17:57 ║       145 ║ R2       ║ NY    ║    1 ║
║ 11/7/2017 15:18:26 ║       145 ║ L3       ║ CT    ║    2 ║
║ 11/7/2017 15:34:24 ║       145 ║ R3       ║ CT    ║    1 ║
║ 11/7/2017 16:02:01 ║       999 ║ L1       ║ NJ    ║    2 ║
║ 11/7/2017 16:22:33 ║       999 ║ R1       ║ NJ    ║    1 ║
║ 11/7/2017 16:23:14 ║       999 ║ L2       ║ WA    ║    3 ║
║ 11/7/2017 16:27:16 ║       999 ║ R2       ║ WA    ║    2 ║
║ 11/7/2017 16:27:46 ║       999 ║ L3       ║ WA    ║    1 ║
╚════════════════════╩═══════════╩══════════╩═══════╩══════╝

我试图将停止字段更改为如下所示

╔════════════════════╦═══════════╦══════════╦═══════╦══════╗
║      ENDTIME       ║ TRAILERID ║ POSITION ║ STORE ║ STOP ║
╠════════════════════╬═══════════╬══════════╬═══════╬══════╣
║ 11/7/2017 15:15:44 ║       145 ║ L1       ║ BOS   ║    3 ║
║ 11/7/2017 15:16:57 ║       145 ║ L2       ║ NY    ║    2 ║
║ 11/7/2017 15:17:24 ║       145 ║ R1       ║ NY    ║    2 ║
║ 11/7/2017 15:17:57 ║       145 ║ R2       ║ NY    ║    2 ║
║ 11/7/2017 15:18:26 ║       145 ║ L3       ║ CT    ║    1 ║
║ 11/7/2017 15:34:24 ║       145 ║ R3       ║ CT    ║    1 ║
║ 11/7/2017 16:02:01 ║       999 ║ L1       ║ NJ    ║    2 ║
║ 11/7/2017 16:22:33 ║       999 ║ R1       ║ NJ    ║    2 ║
║ 11/7/2017 16:23:14 ║       999 ║ L2       ║ WA    ║    1 ║
║ 11/7/2017 16:27:16 ║       999 ║ R2       ║ WA    ║    1 ║
║ 11/7/2017 16:27:46 ║       999 ║ L3       ║ WA    ║    1 ║
╚════════════════════╩═══════════╩══════════╩═══════╩══════╝

我的尝试是使用row_number和排名,但我不能'得到正确的结果。给我第一个表格结果。

SELECT ps.ENDTIME, ps.TRUCKID as TRAILERID, ps.CONTAINERPOSITION as POSITION,ps.STORE,RANK() OVER( PARTITION by ps.STORE  ORDER BY ps.ENDTIME DESC)AS STOP 
FROM TRAILERDATA ps
ORDER BY ps.ENDTIME ASC

最重要的是,即使ENDTIME的顺序不正确,也要按相同等级的商店组进行标记。

1 个答案:

答案 0 :(得分:1)

示例数据

DECLARE @T TABLE 
    (EndTime datetime2(0), TrailerID int, Position varchar(50), Store varchar(50));
INSERT INTO @T (EndTime, TrailerID, Position, Store) VALUES
('2017-11-07 15:15:44',145,'L1','BOS'),
('2017-11-07 15:16:57',145,'L2','NY'),
('2017-11-07 15:17:24',145,'R1','NY'),
('2017-11-07 15:17:57',145,'R2','NY'),
('2017-11-07 15:18:26',145,'L3','CT'),
('2017-11-07 15:34:24',145,'R3','CT'),
('2017-11-07 16:02:01',999,'L1','NJ'),
('2017-11-07 16:22:33',999,'R1','NJ'),
('2017-11-07 16:23:14',999,'L2','WA'),
('2017-11-07 16:27:16',999,'R2','WA'),
('2017-11-07 16:27:46',999,'L3','WA');

<强>查询

WITH
CTE
AS
(
    SELECT
        EndTime, TrailerID, Position, Store
        ,MAX(EndTime) OVER (PARTITION BY TrailerID, Store) AS SortingTime
    FROM @T
)
SELECT
    EndTime, TrailerID, Position, Store
    ,SortingTime
    ,DENSE_RANK() OVER (PARTITION BY TrailerID ORDER BY SortingTime DESC) AS Stop
FROM CTE
ORDER BY TrailerID, Stop DESC, EndTime;

<强>结果

+---------------------+-----------+----------+-------+---------------------+------+
|       EndTime       | TrailerID | Position | Store |     SortingTime     | Stop |
+---------------------+-----------+----------+-------+---------------------+------+
| 2017-11-07 15:15:44 |       145 | L1       | BOS   | 2017-11-07 15:15:44 |    3 |
| 2017-11-07 15:16:57 |       145 | L2       | NY    | 2017-11-07 15:17:57 |    2 |
| 2017-11-07 15:17:24 |       145 | R1       | NY    | 2017-11-07 15:17:57 |    2 |
| 2017-11-07 15:17:57 |       145 | R2       | NY    | 2017-11-07 15:17:57 |    2 |
| 2017-11-07 15:18:26 |       145 | L3       | CT    | 2017-11-07 15:34:24 |    1 |
| 2017-11-07 15:34:24 |       145 | R3       | CT    | 2017-11-07 15:34:24 |    1 |
| 2017-11-07 16:02:01 |       999 | L1       | NJ    | 2017-11-07 16:22:33 |    2 |
| 2017-11-07 16:22:33 |       999 | R1       | NJ    | 2017-11-07 16:22:33 |    2 |
| 2017-11-07 16:23:14 |       999 | L2       | WA    | 2017-11-07 16:27:46 |    1 |
| 2017-11-07 16:27:16 |       999 | R2       | WA    | 2017-11-07 16:27:46 |    1 |
| 2017-11-07 16:27:46 |       999 | L3       | WA    | 2017-11-07 16:27:46 |    1 |
+---------------------+-----------+----------+-------+---------------------+------+

在结果中,您可以看到SortingTime如何计算您需要的DENSE_RANK。从本质上讲,SortingTime定义了TrailerIDStore的分组,并且还方便地提供了一种排序方式。

上述查询依赖EndTime对于不同的Stores不同。更具体地说,MAX时间不同。如果您有两个Stores具有相同的最大EndTime,则查询会为它们分配相同的Stop

如果可能,请将Store添加到ORDER BY

WITH
CTE
AS
(
    SELECT
        EndTime, TrailerID, Position, Store
        ,MAX(EndTime) OVER (PARTITION BY TrailerID, Store) AS SortingTime
    FROM @T
)
SELECT
    EndTime, TrailerID, Position, Store
    ,SortingTime
    ,DENSE_RANK() OVER (PARTITION BY TrailerID ORDER BY SortingTime DESC, Store) AS Stop
FROM CTE
ORDER BY TrailerID, Stop DESC, EndTime;