如何获得每天包含多个列的事件的第一个实例,包括日期时间并返回这些列加上完整的日期时间值?
Posted
技术标签:
【中文标题】如何获得每天包含多个列的事件的第一个实例,包括日期时间并返回这些列加上完整的日期时间值?【英文标题】:How can I get the first instance of an event per day with multiple columns including a datetime and return those columns plus the full datetime value? 【发布时间】:2019-04-17 01:07:37 【问题描述】:我需要生成一个 SQL 脚本,该脚本将使用许多列提取不同的条目,其中之一是日期时间列。我只对每个事件的第一次出现感兴趣,并且查询需要跨越多天。该查询将针对一个非常大的数据库运行,并且可能会返回数十万个结果,如果不是数百万的话。因此,我也需要这个脚本尽可能高效。这最终将是一个在 s-s-rS 中运行以提取访问事务的脚本。
我尝试过使用 GROUP BY、DISTINCT、子查询、FIRST 等,但均未成功。我可以在网上找到的所有示例都没有 JOIN 语句或计算列,例如仅从日期时间字段中收集日期。
我已将以下脚本简化为仅拉一天一扇门,但结果将是多天一扇门。此代码返回我需要的数据,我不关心 COUNT,但我还需要以某种方式在我的结果集中获取 (DateAdd(minute,-(ServerLocaleOffset),ServerUTC))
字段。问题是因为它一直到秒,它使所有记录都不同。
DECLARE @Begin datetime2 = '4/10/2019',
@End datetime2 = '4/11/2019',
@Door varchar(max) = 'Front Entrance'
SELECT
CONVERT(VARCHAR(10), (DateAdd(minute,-(ServerLocaleOffset),ServerUTC)),101) AS 'Date'
,AJ.PrimaryObjectIdentity
,AJ.SecondaryObjectIdentity
,AJ.MessageType
,AJ.PrimaryObjectName
,AJ.SecondaryObjectName
,AP.Text13
,COUNT(*) AS 'Count'
FROM Access.JournalLogView AJ
LEFT OUTER JOIN Access.Personnel as AP on AP.GUID = AJ.PrimaryObjectIdentity
WHERE (MessageType like 'CardAdmitted' OR MessageType like 'CardRejected')
AND (DateAdd(minute,-(ServerLocaleOffset),ServerUTC)) BETWEEN @Begin AND @End
AND (SecondaryObjectName IN (@Door))
GROUP BY CONVERT(VARCHAR(10), (DateAdd(minute,-(ServerLocaleOffset),ServerUTC)),101)
,PrimaryObjectIdentity
,SecondaryObjectIdentity
,MessageType
,PrimaryObjectName
,SecondaryObjectName
,Text13
ORDER BY AJ.PrimaryObjectName
我想获取 SELECT 语句中调用的列以及包含第二个的日期时间。同样,我也想要最有效的方式来提取这些数据。非常感谢。
【问题讨论】:
能否提供一下带有日期时间列的表结构? ServerUTC 是 datetime2 列,serverlocaloffset 只记录距 GMT 多少分钟是服务器的时区。 好吧……即使这样,我的查询也应该可以了……你试过了吗……?? 【参考方案1】:假设 PrimaryObjectIdentity 是在 JournalLogview 和 ServerLocaleOffset 中查找人员的主键作为该表中的 datetime 列,我已经写下了:
DECLARE @Begin datetime2 = '4/10/2019',
@End datetime2 = '4/11/2019',
@Door varchar(max) = 'Front Entrance'
WITH cte
AS(
SELECT
ROW_NUMBER() OVER
(PARTITION BY PrimaryObjectIdentity,CONVERT(VARCHAR(10), (DateAdd(minute,-(ServerLocaleOffset),ServerUTC)),101) ORDER BY ServerLocaleOffset) AS row_num,
--whatever the columns you want here
*
FROM
Access.JournalLogView)
SELECT
DateAdd(minute,-(ServerLocaleOffset),ServerUTC)) AS 'DateTime'
,AJ.PrimaryObjectIdentity
,AJ.SecondaryObjectIdentity
,AJ.MessageType
,AJ.PrimaryObjectName
,AJ.SecondaryObjectName
,AP.Text13
--I guess count(*) won't be of use a we are selecting only the first row
,COUNT(*) AS 'Count'
FROM cte AJ
LEFT OUTER JOIN
Access.Personnel as AP
on
AP.GUID = AJ.PrimaryObjectIdentity
WHERE
AJ.row_num = 1
AND (MessageType like 'CardAdmitted' OR MessageType like 'CardRejected')
AND (DateAdd(minute,-(ServerLocaleOffset),ServerUTC)) BETWEEN @Begin AND @End
AND (SecondaryObjectName IN (@Door))
GROUP BY (DateAdd(minute,-(ServerLocaleOffset),ServerUTC))
,PrimaryObjectIdentity
,SecondaryObjectIdentity
,MessageType
,PrimaryObjectName
,SecondaryObjectName
,Text13
ORDER BY AJ.PrimaryObjectName
在此查询中,我使用 PARTITION 按每个用户、日期对整个表进行分区,然后从每个用户在该特定日期的第一个条目开始将 row_number() 分配给每一行。因此,任何 row_num() = 1 的行都会为您提供该用户在该日期的第一个条目(这与我在 where 子句中使用的条件相同)。希望这会有所帮助:)
【讨论】:
以上是关于如何获得每天包含多个列的事件的第一个实例,包括日期时间并返回这些列加上完整的日期时间值?的主要内容,如果未能解决你的问题,请参考以下文章