Sql p>
第一部分是通过查找起始日期和结束日期之间缺少日期来查找缺少的日期范围,然后将它们插入表中进行审核,但它将保存我正在查找的缺少日期:Sql p>,sql,sql-server,common-table-expression,Sql,Sql Server,Common Table Expression,第一部分是通过查找起始日期和结束日期之间缺少日期来查找缺少的日期范围,然后将它们插入表中进行审核,但它将保存我正在查找的缺少日期: ;WITH NullGaps AS( SELECT ROW_NUMBER() OVER (ORDER BY ChannelName, ReadingDate) AS ID,SerialNumber, ReadingDate, ChannelName, uid FROM [Staging].[UriData] )
;WITH NullGaps AS(
SELECT ROW_NUMBER() OVER (ORDER BY ChannelName, ReadingDate) AS ID,SerialNumber, ReadingDate, ChannelName, uid
FROM [Staging].[UriData]
)
INSERT INTO [Staging].[MissingDates]
SELECT (DATEDIFF(MINUTE, g1.ReadingDate , g2.ReadingDate) / 15) -1 AS 'MissingCount',
g1.ChannelName,
g1.SerialNumber,
g1.ReadingDate AS FromDate,
g2.ReadingDate AS ToDate
FROM NullGaps g1
INNER JOIN NullGaps g2
ON g1.ID = (g2.ID - 1)
WHERE DATEADD(MINUTE, 15, g1.ReadingDate) < g2.ReadingDate
AND g1.ChannelName IN (SELECT ChannelName FROM staging.ActiveChannels)
AND NOT EXISTS(
SELECT 1 FROM [Staging].[MissingDates] m
WHERE m.Channel = g1.ChannelName
AND m.Serial = g1.SerialNumber
AND m.FromDate = g1.ReadingDate
AND m.ToDate = g2.ReadingDate
)
我相信您可以对此进行改进。此解决方案只查找缺少的日期,并允许我仅用缺少的日期来填充数据表。如果其他设备需要用于不同的时间间隔,我也可以在以后更改时间间隔。我已经将查询放在两个特殊存储过程中,以便我可以控制两个APECT,一个用于审核,另一个用于回填。这种类型的查询经常出现,您没有找到其他有帮助的so答案吗?有些人建议保留日期时间表,因为有些设备是按第二个顺序运行的,这将是一个巨大的设备,250个频道,我将进入数万亿行,其他人建议联合,但键入日期范围。我想要更有活力的东西。我正在学习SQL,并与其中的一些概念作斗争。您可以创建一个满足您的时间间隔需要的日期时间表。15分钟的间隔是每天96条记录——这几乎不可怕。现有技术可以动态生成日期范围,然后将稀疏数据连接到生成的“保证所有间隔”数据中。动态生成可能比只保留datetime或数字表更昂贵,这取决于您使用它的频率和方式。但不可辩驳的是,它一次又一次地出现在这里,所以会有一些很好的参考资料用于各种各样的研究techniques@Caius谢谢你,我在这里看到的一些东西说,创造每一个可能的日期。我也会看一看这些。这种类型的问题经常出现,你没有找到任何其他有帮助的答案吗?一些人建议保持一个日期时间表,因为一些设备由秒运行,这将是巨大的,250个频道一个设备,我将进入数万亿行,其他人建议一个联盟,但是键入日期范围。我想要更有活力的东西。我正在学习SQL,并与其中的一些概念作斗争。您可以创建一个满足您的时间间隔需要的日期时间表。15分钟的间隔是每天96条记录——这几乎不可怕。现有技术可以动态生成日期范围,然后将稀疏数据连接到生成的“保证所有间隔”数据中。动态生成可能比只保留datetime或数字表更昂贵,这取决于您使用它的频率和方式。但不可辩驳的是,它一次又一次地出现在这里,所以会有一些很好的参考资料用于各种各样的研究techniques@Caius谢谢你,我在这里看到的一些东西说,创造每一个可能的日期。我还将看一下这些。查询获取两个时间间隔缺失的日期,缺失计数告诉我这两个时间间隔缺失了多少。它还为我提供了选择特定频道、设备和日期的选项。然后,如果需要,我可以设置一个已处理标志和一个空标志(一旦我了解了如何做。)@TheRangeGoblin。我不明白的是为什么不使用
lag()
。如果您的查询有效,那么这与您的问题无关。这一部分似乎比必要的更复杂,但与问题无关。我一直在学习SQL,我所做的所有培训都没有提到滞后,并告诉我按图所示去做。我会检查一下滞后,看看是否能得到我的解决方案。谢谢你这样告诉我。这个查询获取两个时间间隔缺失的日期,缺失计数告诉我这两个时间间隔缺失了多少。它还为我提供了选择特定频道、设备和日期的选项。然后,如果需要,我可以设置一个已处理标志和一个空标志(一旦我了解了如何做。)@TheRangeGoblin。我不明白的是为什么不使用lag()
。如果您的查询有效,那么这与您的问题无关。这一部分似乎比必要的更复杂,但与问题无关。我一直在学习SQL,我所做的所有培训都没有提到滞后,并告诉我按图所示去做。我会检查一下滞后,看看是否能得到我的解决方案。谢谢你这样指我。它工作得很好,但我想我需要添加一个最小和最大日期,因为它是从第一个日期和最后一个日期开始的一整天,所以我有我不想要的时间。我在一个更大的数据集上运行了它,它添加了不应该存在的日期。我是否需要添加到另一个联合,以便我可以设置开始和结束日期(这可能因不同的设备而不同,并且有数千台设备)…我还应该说,我已尝试将MIN(日期)添加到查询中,但我得到一个错误:groupby,have,或者在递归公共表表达式“RCTE”的递归部分不允许使用聚合函数。@TheRangeGoblin好吧,这种方法基本上是每15分钟查找一次间隔日期时间。您可以通过选择[SerialNumber]、[ChannelName]、[ReadingDate]作为FromDate、DATEADD(分钟,15,[ReadingDate])作为ToDate来更改外部查询中的选择。但我不确定那是你想要的?就是这样。。。数据可能在某一天的14:15开始,在另一天的16:15结束,它应该从这些日期时间开始和结束,在mo'it’s回填并向前填充到午夜,以及查找丢失的数据。不幸的是,每台设备都有不同的开始日期时间。@TheRangeGoblin请查看刚才包含的新查询。它工作正常,但我认为需要添加一个最小和最大日期,因为它从第一个日期和最后一个日期开始一整天,所以我有不想要的时间。我在一个更大的数据集上运行了它,它添加了不应该存在的日期。我是否需要添加到另一个联合,以便我可以设置开始和结束日期(这可能会因不同的设备而有所不同,也可能会有所不同)
--------------------------------------------------------------
| MissingCount | FromDate | ToDate |
--------------------------------------------------------------
| 2 | 2018-09-20 14:30:00 | 2018-09-20 15:15:00 |
| 1 | 2018-09-20 15:30:00 | 2018-09-20 16:00:00 |
| 1 | 2018-09-20 20:30:00 | 2018-09-20 21:00:00 |
--------------------------------------------------------------
with missing as (<your query here>)
cte as (
select dateadd(minute, 15, fromdate) as dte, missingcount - 1 as missingcount
from missing
union all
select dateadd(minute, 15, dte), missingcount - 1
from cte
where missingcount > 0
)
select *
from cte;
WITH RCTE AS
(
select [SerialNumber], [ChannelName], 0 as Lvl, cast(cast([ReadingDate] as date) as datetime) as ReadingDate
from [UriData]
group by SerialNumber, [ChannelName], cast([ReadingDate] as date)
union all
select [SerialNumber], [ChannelName], Lvl + 1, DATEADD(MINUTE,15,[ReadingDate])
from RCTE
where cast([ReadingDate] as date) = cast(DATEADD(MINUTE,15,[ReadingDate]) as date)
)
SELECT [SerialNumber], [ChannelName], [ReadingDate] AS FromDate
FROM RCTE r
WHERE NOT EXISTS
(
select 1
from [UriData] t
where t.[SerialNumber] = r.[SerialNumber]
and t.[ChannelName] = r.[ChannelName]
and t.[ReadingDate] = r.[ReadingDate]
);
WITH CTE AS
(
SELECT SerialNumber, ChannelName, ReadingDate,
LAG(ReadingDate) OVER (PARTITION BY SerialNumber, ChannelName ORDER BY ReadingDate) AS prevReadingDate
FROM [UriData]
)
, RCTE AS
(
select SerialNumber, ChannelName, 0 as Lvl,
prevReadingDate AS ReadingDate,
prevReadingDate AS MinReadingDate,
ReadingDate AS MaxReadingDate
from CTE
where DATEDIFF(MINUTE, prevReadingDate, ReadingDate) > 15
union all
select SerialNumber, ChannelName, Lvl + 1,
DATEADD(MINUTE,15,ReadingDate),
MinReadingDate,
MaxReadingDate
from RCTE
where ReadingDate < DATEADD(MINUTE,-15,MaxReadingDate)
)
select SerialNumber, ChannelName,
ReadingDate AS FromDate,
DATEADD(MINUTE,15,ReadingDate) AS ToDate,
dense_rank() over (partition by SerialNumber, ChannelName order by MinReadingDate) as GapRank,
(DATEDIFF(MINUTE, MinReadingDate, MaxReadingDate) / 15) AS TotalMissingQuarterGaps
from RCTE
where Lvl > 0 AND MinReadingDate < MaxReadingDate
ORDER BY SerialNumber, ChannelName, MinReadingDate;
;WITH NullGaps AS(
SELECT ROW_NUMBER() OVER (ORDER BY ChannelName, ReadingDate) AS ID,SerialNumber, ReadingDate, ChannelName, uid
FROM [Staging].[UriData]
)
INSERT INTO [Staging].[MissingDates]
SELECT (DATEDIFF(MINUTE, g1.ReadingDate , g2.ReadingDate) / 15) -1 AS 'MissingCount',
g1.ChannelName,
g1.SerialNumber,
g1.ReadingDate AS FromDate,
g2.ReadingDate AS ToDate
FROM NullGaps g1
INNER JOIN NullGaps g2
ON g1.ID = (g2.ID - 1)
WHERE DATEADD(MINUTE, 15, g1.ReadingDate) < g2.ReadingDate
AND g1.ChannelName IN (SELECT ChannelName FROM staging.ActiveChannels)
AND NOT EXISTS(
SELECT 1 FROM [Staging].[MissingDates] m
WHERE m.Channel = g1.ChannelName
AND m.Serial = g1.SerialNumber
AND m.FromDate = g1.ReadingDate
AND m.ToDate = g2.ReadingDate
)
;WITH MissingDateTime AS(
SELECT DATEADD(MINUTE, 15, FromDate) AS dte, MissingCount -1 AS MissingCount, Serial, Channel
FROM [Staging].[MissingDates]
UNION ALL
SELECT DATEADD(MINUTE, 15, dte), MissingCount - 1, Serial, Channel
FROM MissingDateTime
WHERE MissingCount > 0
) -- END CTE
INSERT INTO [Staging].[UriData]
SELECT NEWID(), Serial, Channel, '999', '0', dte, CURRENT_TIMESTAMP, 0,1,0 FROM MissingDateTime m
WHERE NOT EXISTS(
SELECT 1 FROM [Staging].[UriData] u
WHERE u.ChannelName = m.Channel
AND u.SerialNumber = m.Serial
AND u.ReadingDate = m.dte
) -- END SELECT