在几分钟内检查SQL中的缺少时间间隔

时间:2016-08-02 04:17:11

标签: sql sql-server

我有一个如下的SQL语句,我希望以D.DatalogValue没有任何值的时间间隔(以分钟为单位)检查数据,并且它不会显示为空值或零值无论是。如下输出结果的样本将显示2016-06-01 00:32:29作为缺少createdDate。

SELECT 
    A.DefID, A.ObjID, 
    C.ObjName, C.Dev_ID,
    A.Pro_ID, A.ArrayIndex,
    A.DefType, A.TObjID, A.DimeId, A.DefId,
    D.DatalogValue, D.PanelDt, D.CreatedDate
FROM 
    Table A, Table C, Table D
WHERE 
    A.ObjID = C.ObjID
    AND C.ObjID = '2627'
    AND A.DefID = D.DefID
    AND D.CreatedDate BETWEEN '2016-06-01' AND '2016-06-02'
ORDER BY 
    C.ObID,C.ObjName;

示例数据:

Create Date             DatalogValue
-------------------------------------
2016-06-01 00:29:29     0.01
2016-06-01 00:30:29     0.02
2016-06-01 00:31:29     0.03

2016-06-01 00:33:29     0.04

通过使用提供的解决方案我已经出来了一个SQL语句,但它仍然无法显示我想要的结果。我不确定哪个部分我的代码错误如下:

 DECLARE @StartDate DATETIME = '2016-07-01';
 DECLARE @EndDate DATETIME = '2016-07-31';

WITH Check_Dates AS (
SELECT @StartDate [Date] 
UNION ALL 
SELECT DATEADD(MINUTE, 1, [Date]) FROM Check_Dates
WHERE [Date] < DATEADD(DAY, 1, @EndDate)
)

SELECT 
FORMAT(d.Date, 'yyyy-MM-dd HH:mm') [Created Date]

FROM Check_Dates d
WHERE 
NOT EXISTS(
SELECT 
Format(D.CreatedDate, 'yyyy-MM-dd HH:mm')as created_dt

FROM TABLE A
,TABLE C
,TABLE D
WHERE A.ObjID=C.ObjID
AND C.ObjID IN('3915')
AND A.DefID=D.DefID
AND D.CreatedDate BETWEEN '2016-07-01' AND '2016-08-01'
)

OPTION (MAXRECURSION 0);

2 个答案:

答案 0 :(得分:0)

解决方案是使用CTE在原始查询中创建DATETIME s然后LEFT JOIN这些列表。您也可以创建一对表(如评论中所述) - 谷歌DimDate和/或DimTime。

像(未经测试)的东西:

DECLARE @StartDate DATETIME = '2016-06-01';
DECLARE @EndDate DATETIME = '2016-06-02';

WITH Dates AS (
    SELECT @StartDate [Date] 
    UNION ALL 
    SELECT DATEADD(SECOND, 1, [Date]) FROM Dates
    WHERE [Date] < DATEADD(DAY, 1, @EndDate)
)
SELECT 
 d.Date [Created Date]
 ,COALESCE(Qry.DatalogValue, 0) DatalogValue
FROM Dates d
LEFT JOIN (
   Your query goes here
) Qry
ON d.Date = Qry.CreatedDate
OPTION (MAXRECURSION 0)

答案 1 :(得分:0)

您的解决方案对我来说似乎非常危险。你确定应该比较秒吗?我会截断到几分钟。我建议更强大的解决方案:

<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.21.0/ramda.min.js"></script>

请注意,所有日期都会截断为几分钟。您可以通过删除数字生成部分来简单地查询(数字可以放在实用程序表中,1440值,如果这就是您需要的全部)。可以预先计算最小值和最大值。

这导致以下输出(可以处理范围minDate + 999999分钟,可以简单地扩展):

WITH Dates AS
( --Your dates and values
    SELECT * FROM (VALUES
    ('2016-06-01 00:29:29', 0.01),
    ('2016-06-01 00:30:29', 0.02),
    ('2016-06-01 00:31:29', 0.03),
    ('2016-06-01 00:33:29', 0.04)--,('2016-06-01 01:00:28', 0.05)
    ) T(CreateDate, CatalogValues)
), Minute10 AS --Generate numbers from 0-999999
(
    SELECT * FROM (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(0)) T1(Value)
), Minute1000 AS
(
    SELECT M1.Value FROM Minute10 M1 CROSS JOIN Minute10 M2 CROSS JOIN Minute10
), Minute1000000 AS
(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1))-1 Value
    FROM Minute1000
    CROSS JOIN Minute1000 M2
), RangeValues AS --for simplicity, min and max values from dates
(
    SELECT DATEADD(MINUTE, DATEDIFF(MINUTE, 0, MIN(CreateDate)), 0) MinDate,
           DATEADD(MINUTE, DATEDIFF(MINUTE, 0, MAX(CreateDate)), 0) MaxDate
    FROM Dates
)
SELECT TOP(1+DATEDIFF(MINUTE, (SELECT MinDate FROM RangeValues), (SELECT MaxDate FROM RangeValues)))
DATEADD(MINUTE,Value,MinDate) ExpectedDate, CreateDate, CatalogValues
FROM Minute1000000
CROSS APPLY (SELECT MinDate FROM RangeValues) T
LEFT JOIN Dates ON DATEADD(MINUTE,Value,MinDate)=DATEADD(MINUTE, DATEDIFF(MINUTE, 0, CreateDate), 0)

<强>解释

日期只是源表。表ExprectedDate CreateDate CatalogValues 2016-06-01 00:29:00.000 2016-06-01 00:29:29 0.01 2016-06-01 00:30:00.000 2016-06-01 00:30:29 0.02 2016-06-01 00:31:00.000 2016-06-01 00:31:29 0.03 2016-06-01 00:32:00.000 NULL NULL 2016-06-01 00:33:00.000 2016-06-01 00:33:29 0.04 .. Minute10用于生成0到999999之间的数字(10个交叉连接10 = 100,100个交叉连接x3 = 100 ^ 3 = 1000000.上表中的记录编号为获取连续值不要担心,TOP会阻止评估所有1000000个值。Minute1000000包含MAX和MIN日期,为简单起见。

<强>算法:

由于您需要每分钟从MIN日期到MAX日期的记录,因此您评估RangeValues条记录(+1以避免Fencepost错误)。所有必需的表都已连接(TOP DATETIFF(MINUTE,MIN,MAX)+1将MIN列添加到每个记录中),预期日期计算为MIN日期+连续值(以分钟为单位)。上次加入,LEFT 1,将每分钟生成的日期与源表进行匹配。如果匹配,则附加(加入)记录。如果没有匹配,则追加NULL。注意`DATEADD(MINUTE,DATEDIFF(MINUTE,0,@ someDate),0)'截断日期的秒数。