TSQL在同一列A上放置相同的等级/行号,但一旦A列更改就会增加
Posted
技术标签:
【中文标题】TSQL在同一列A上放置相同的等级/行号,但一旦A列更改就会增加【英文标题】:TSQL Put same rank/row number on same column A but increment once column A changes 【发布时间】:2017-02-08 06:20:18 【问题描述】:我有这张表,我想将排名/行号放入具有以下条件的行
-
相同的 IO 将具有相同的等级/行号
一旦下一行的 IO 与上一行不同,排名/行号就会增加。
表格按 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
【问题讨论】:
这个链接会帮助你***.com/questions/41949621/… sql 2008没有滞后功能 有多个带有/不带有滞后功能的答案...您是否检查过第二个答案(带有递归 cte)???? 是的,这就是我用来解决问题的方法。谢谢 看起来像gaps-and-islands
... 是否要重新开始对每个UserID
和AccessDate
进行排名?
【参考方案1】:
我已使用您的查询结果集的输出作为输入。并编写查询以获得预期的结果集。您必须通过查看以下查询来更改您的 order by 子句与 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
【讨论】:
问题是当小时和分钟部分对于相同的IO不同时,排名也会不同,导致输出不正确......【参考方案2】:有趣的问题。我已经玩了一点,这就是我想出的。这不是我制作过的最优雅的东西,但似乎做对了。我正在使用表变量@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 上也可以工作。只需修复 prepare test data 部分,不要在输出中使用 date
和 time
转换。 p>
【讨论】:
感谢回复可惜只用sql server 2008,这个版本的sql没有滞后功能 @DennisLim 你注意到我为 Sql Server 2008 添加了一个单独的示例吗?以上是关于TSQL在同一列A上放置相同的等级/行号,但一旦A列更改就会增加的主要内容,如果未能解决你的问题,请参考以下文章