我有一个如下的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);
答案 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)'截断日期的秒数。