如何获取每天包含日期时间和 return 这些列以及完整日期时间值的多列事件的第一个实例?

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?

我需要生成一个 SQL 脚本,该脚本将使用多个列提取不同的条目,其中一个是日期时间列。我只对每个事件当天第一次出现感兴趣,查询需要跨越多天。该查询将 运行 针对一个非常大的数据库,并且可能返回数十万甚至数百万个结果。因此,我也需要这个脚本尽可能高效。这最终将成为 SSRS 中用于拉取访问事务的脚本 运行ning。

我尝试过使用 GROUP BY、DISTINCT、子查询、FIRST 等,但均未成功。我可以在网上找到的所有示例都没有 JOIN 语句或计算列,例如仅从日期时间字段收集日期。

我已经将下面的脚本简化了一些,只拉了一天和一扇门,但产品将是多天和多扇门。此代码 returns 我需要的数据,我不关心 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 语句中调用的列以及包含第二个日期时间的日期时间。同样,我也想要最有效的方法来提取这些数据。非常感谢。

假设PrimaryObjectIdentity是在JournalLogview和ServerLocaleOffset中找到人员的主键作为table中的日期时间列,我记下了这个:

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 按每个用户、日期对整个 table 进行分区,然后将 row_number() 分配给从每个用户的第一个条目开始的每一行特定日期。因此,任何带有 row_num() = 1 的行都会为您提供该用户在该日期的第一个条目(这与我在 where 子句中使用的条件相同)。希望这会有所帮助:)