TSQL在同一列A上放置相同的排名/行号,但在列A更改后递增

时间:2017-02-08 06:20:19

标签: sql-server sql-server-2008 tsql

我有这个表,我想在具有以下条件的行中添加排名/行号

  1. 相同的IO将具有相同的排名/行号
  2. 如果下一行中的IO与上一行不同,则排名/行号将增加。
  3. 表按AccessDate排序,然后按AccessTime排序,并按UserID

    分组

    我正在使用此查询,但输出不是我想要的。

    SELECT
        ATTCHECKINOUT.UserID,
        AccessDate = CAST(CheckTime as date),
        AccessTime = CAST(CheckTime as time),
        CheckType, 
        Ranking = DENSE_RANK() over(partition by ATTCHECKINOUT.UserID, CAST(CheckTime as date) order by CheckType)
    FROM ATTCHECKINOUT INNER JOIN ATTUSER ON ATTCHECKINOUT.UserID=ATTUSER.UserID   
    WHERE CheckTime BETWEEN '1/6/2017' AND '1/10/2017' AND ATTUSER.BadgeNumber = 10311
    ORDER BY ATTCHECKINOUT.UserID, CheckTime
    

    查询输出

    UserID |AccessDate |AccessTime |IO |Ranking
    8394   |2017-01-06 |11:24:10   |I  |1
    8394   |2017-01-06 |11:24:15   |I  |1
    8394   |2017-01-06 |13:05:13   |O  |2
    8394   |2017-01-06 |13:05:18   |O  |2
    8394   |2017-01-06 |13:34:17   |I  |1
    8394   |2017-01-06 |13:34:20   |I  |1
    8394   |2017-01-06 |20:35:01   |O  |2
    8394   |2017-01-06 |20:35:05   |O  |2
    8394   |2017-01-07 |10:59:49   |I  |1
    8394   |2017-01-07 |10:59:52   |I  |1
    8394   |2017-01-07 |17:02:54   |O  |2
    8394   |2017-01-07 |17:29:39   |I  |1
    8394   |2017-01-07 |17:29:43   |I  |1
    8394   |2017-01-07 |20:13:02   |O  |2
    8394   |2017-01-07 |20:13:05   |O  |2
    8394   |2017-01-09 |08:32:38   |I  |1
    8394   |2017-01-09 |08:32:45   |I  |1
    8394   |2017-01-09 |20:02:52   |O  |2
    8394   |2017-01-09 |20:02:55   |O  |2
    

    我希望输出像这样

    UserID |AccessDate |AccessTime |IO |Ranking
    8394   |2017-01-06 |11:24:10   |I  |1
    8394   |2017-01-06 |11:24:15   |I  |1
    8394   |2017-01-06 |13:05:13   |O  |2
    8394   |2017-01-06 |13:05:18   |O  |2
    8394   |2017-01-06 |13:34:17   |I  |3
    8394   |2017-01-06 |13:34:20   |I  |3
    8394   |2017-01-06 |20:35:01   |O  |4
    8394   |2017-01-06 |20:35:05   |O  |4
    8394   |2017-01-07 |10:59:49   |I  |1
    8394   |2017-01-07 |10:59:52   |I  |1
    8394   |2017-01-07 |17:02:54   |O  |2
    8394   |2017-01-07 |17:29:39   |I  |3
    8394   |2017-01-07 |17:29:43   |I  |3
    8394   |2017-01-07 |20:13:02   |O  |4
    8394   |2017-01-07 |20:13:05   |O  |4
    8394   |2017-01-09 |08:32:38   |I  |1
    8394   |2017-01-09 |08:32:45   |I  |1
    8394   |2017-01-09 |20:02:52   |O  |2
    8394   |2017-01-09 |20:02:55   |O  |2
    

2 个答案:

答案 0 :(得分:0)

我已将查询结果集的输出用作输入。并编写查询以获得预期的结果集。您必须通过查看以下查询来更改您的order by子句in dense_rank函数。

SELECT UserID,
       [AccessDate],
       [AccessTime],
       [IO],
       Dense_rank()
         OVER(
           partition BY UserID, [AccessDate]
           ORDER BY userid, [AccessDate], Datepart(hour, [AccessTime]), Datepart(minute, [AccessTime]),[IO]) Ranking
FROM   #table1 -- this contains result set of your output query

答案 1 :(得分:0)

有趣的问题。我已经玩了一下,这就是我想出来的。不是我制作过的最优雅的东西,但似乎做得对。我使用表变量@t来保存ATTCHECKINOUT表中的值:

-- prepare test data
-- note: added some additional rows to test correctness

declare @t table (
    UserID int not null,
    CheckTime datetime not null,
    CheckType nvarchar(1) not null
)

insert into @t (UserID, CheckTime, CheckType) 
values
    (8394   ,'2017-01-06 11:24:10'   ,'I'), (8394   ,'2017-01-06 11:24:15'   ,'I'), 
    (8394   ,'2017-01-06 13:05:13'   ,'O'), (8394   ,'2017-01-06 13:05:18'   ,'O'),
    (8394   ,'2017-01-06 13:34:17'   ,'I'), (8394   ,'2017-01-06 13:34:20'   ,'I'),
    (8394   ,'2017-01-06 20:35:01'   ,'O'), (8394   ,'2017-01-06 20:35:05'   ,'O'),
    (8394   ,'2017-01-07 10:59:49'   ,'I'), (8394   ,'2017-01-07 10:59:52'   ,'I'),
    (8394   ,'2017-01-07 17:02:54'   ,'O'), (8394   ,'2017-01-07 17:29:39'   ,'I'),
    (8394   ,'2017-01-07 17:29:43'   ,'I'), (8394   ,'2017-01-07 20:13:02'   ,'O'),
    (8394   ,'2017-01-07 20:13:05'   ,'O'), (8394   ,'2017-01-07 20:14:08'   ,'O'),
    (8394   ,'2017-01-07 23:14:08'   ,'O'), (8394   ,'2017-01-09 08:32:38'   ,'I'),
    (8394   ,'2017-01-09 08:32:45'   ,'I'), (8394   ,'2017-01-09 20:02:52'   ,'O'),
    (8394   ,'2017-01-09 20:02:55'   ,'O'), (8395   ,'2017-01-06 11:24:10'   ,'I'),
    (8395   ,'2017-01-06 11:24:15'   ,'I'), (8395   ,'2017-01-06 13:05:13'   ,'O'),
    (8395   ,'2017-01-06 13:05:18'   ,'O'), (8395   ,'2017-01-06 13:09:32'   ,'O'),
    (8395   ,'2017-01-06 13:34:17'   ,'I'), (8395   ,'2017-01-06 13:34:20'   ,'I')

-- produce output

select UserID,
    cast(CheckTime as date) as AccessDate,
    cast(CheckTime as time) as AccessTime,
    CheckType,
    dense_rank() over (order by groupKey) as [rank]
from (
    select UserID, CheckTime, CheckType,
        max(newGroup) over (order by UserId, CheckTime, CheckType ROWS UNBOUNDED PRECEDING ) as groupKey
    from (
        select UserId,
            CheckTime,
            CheckType,
            case 
                when CheckType = lag(CheckType, 1, '') over (order by UserId, CheckTime) 
            then 
                null 
            else 
                row_number() over (order by UserId, CheckTime, CheckType) 
            end as newGroup
        from @t
        where CheckTime >= '2017-01-06 13:05:17.000' -- note where clause here
            and UserID = 8394                        -- note where clause here
    ) as innerSub
) as outerSub
order by UserId, CheckTime, CheckType

输出:

+--------+------------+------------------+-----------+------+
| UserID | AccessDate |    AccessTime    | CheckType | rank |
+--------+------------+------------------+-----------+------+
|   8394 | 2017-01-06 | 13:05:18.0000000 | O         |    1 |
|   8394 | 2017-01-06 | 13:34:17.0000000 | I         |    2 |
|   8394 | 2017-01-06 | 13:34:20.0000000 | I         |    2 |
|   8394 | 2017-01-06 | 20:35:01.0000000 | O         |    3 |
|   8394 | 2017-01-06 | 20:35:05.0000000 | O         |    3 |
|   8394 | 2017-01-07 | 10:59:49.0000000 | I         |    4 |
|   8394 | 2017-01-07 | 10:59:52.0000000 | I         |    4 |
|   8394 | 2017-01-07 | 17:02:54.0000000 | O         |    5 |
|   8394 | 2017-01-07 | 17:29:39.0000000 | I         |    6 |
|   8394 | 2017-01-07 | 17:29:43.0000000 | I         |    6 |
|   8394 | 2017-01-07 | 20:13:02.0000000 | O         |    7 |
|   8394 | 2017-01-07 | 20:13:05.0000000 | O         |    7 |
|   8394 | 2017-01-07 | 20:14:08.0000000 | O         |    7 |
|   8394 | 2017-01-07 | 23:14:08.0000000 | O         |    7 |
|   8394 | 2017-01-09 | 08:32:38.0000000 | I         |    8 |
|   8394 | 2017-01-09 | 08:32:45.0000000 | I         |    8 |
|   8394 | 2017-01-09 | 20:02:52.0000000 | O         |    9 |
|   8394 | 2017-01-09 | 20:02:55.0000000 | O         |    9 |
+--------+------------+------------------+-----------+------+

编辑:这是适用于SQL Server 2008的新版本。准备测试数据与以前相同。

;with cte as (
    select UserID, CheckTime, CheckType,
        (case when sub.CheckType != sub.PrevCheckType then sub.RowNum else null end) as Indicator
    from (
        select UserID, CheckTime, CheckType, 
            ISNULL((
                select top 1 CheckType 
                from @t as innerT
                where t.UserID = innerT.UserID 
                    and t.CheckTime > innerT.CheckTime 
                order by UserID, CheckTime desc), '') as PrevCheckType
            , row_number() over (order by UserID, CheckTime, CheckType) as RowNum
        from @t as t
        where CheckTime >= '2017-01-06 13:05:17.000' -- note where clause here
            and UserID = 8394                        -- note where clause here
    ) sub
)
select UserID,
    cast(CheckTime as date) as AccessDate, 
    cast(CheckTime as time) as AccessTime, 
    CheckType,
    dense_rank() over (partition by UserID order by UserID, ISNULL(Indicator, (select top 1 Indicator from cte innerCte where outerCte.UserID = innerCte.UserID and outerCte.CheckTime > innerCte.CheckTime and Indicator is not null order by UserID, CheckTime desc))) as [Rank]
from cte outerCte
order by UserID, CheckTime, CheckType

可以轻松修改此版本以在Sql Server 2005上运行。只需修复准备测试数据部分,不要使用datetime强制转换在输出中。