[英]select / update SQL records that has a timestamp difference of more then 30 days
我需要 select 或更新上次访问后日期差超过 30 天的徽章记录中的记录。 一个 select 查询可以找到它们,所以我可以更新它们。 很难详细解释,但我举个例子:(这是一个人们扫描徽章并记录时间戳的访问系统。)我只需要在徽章进入系统超过30天时知道记录。在上一次扫描之后,+ 第一次扫描。 示例表显示了我需要的记录(我需要 5 条记录)
只有相同徽章编号的记录必须进行比较和更新。
这可以使用 TSQL 吗?
例子:
+------------------+--------------+
| TimeStamp | Badge |
+------------------+--------------+
| 19-10-2022 10:18 | Badge1 | <--- **select** (more the 30 days after previous scan)
| 01-01-2022 12:18 | Badge1 | <--- ok (less then 30 days)
| 08-12-2021 13:23 | Badge1 | <--- ok (less then 30 days)
| 20-11-2021 11:18 | Badge1 | <--- ok (less then 30 days)
| 22-10-2021 13:18 | Badge1 | <--- **select** (more the 30 days after previous scan)
| 23-08-2020 14:18 | Badge1 | <--- **select** (first entrance)
| 01-01-2022 09:18 | Badge12 | <--- ok (less then 30 days)
| 02-12-2021 10:18 | Badge12 | <--- **select** (more the 30 days after previous scan)
| 29-10-2021 23:18 | Badge12 | <--- ok (less then 30 days)
| 25-10-2021 12:18 | Badge12 | <--- **select** (first entrance)
+------------------+---------+----+
使用这个小提琴有示例数据库和我的错误答案https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=c1528618004f0fe6bb6319e8e638abae
帮助别人帮助你。 发布一个包含 DDL 和示例数据的脚本,可以作为编写代码的基础。
with cte as (
select *, ROW_NUMBER() over (partition by Badge order by Timestamp) as rno
from @x
)
select cte.*, prior.rno as prno, datediff(day, prior.TimeStamp, cte.Timestamp) as ddif
from cte
left join cte as prior on cte.badge = prior.badge and cte.rno - 1 = prior.rno
where cte.rno = 1 or datediff(day, prior.TimeStamp, cte.Timestamp) > 30
order by cte.Badge, cte.TimeStamp;
这应该可行,但我无法在 2008 年进行测试。 小提琴来演示。 注释掉 WHERE 子句以查看为查询逻辑计算的所有行和列。 这使用 ROW_NUMBER 生成序列号,然后使用该值简单地自连接以模拟 LAG。
更新的小提琴: https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=a24d23f54030d7aadd8f889819cd4512
;WITH Ordered AS (
SELECT *
, ROW_NUMBER() OVER (PARTITION BY Badge ORDER BY CONVERT(DATETIME, [scandate] ,103) DESC) rn
FROM History
)
SELECT M.*, DATEDIFF(dd, p.[scandate],m.[scandate]) DaysGap
FROM Ordered M
LEFT JOIN Ordered P
ON M.rn = P.rn-1
AND M.Badge = P.Badge
WHERE P.rn IS NULL -- first entrance
OR DATEDIFF(dd, p.[scandate],m.[scandate]) > 30
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.