我有这个表,我想在具有以下条件的行中添加排名/行号
表按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
答案 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上运行。只需修复准备测试数据部分,不要使用date
和time
强制转换在输出中。