您要求的是“plain sql”,这是一个使用 SQL 和 cmets 进行测试的尝试,它给出了所需的答案。
我已经在 windows xp 上使用“sqlite”和“mysql”测试了代码。它是纯 SQL,应该适用于任何地方。
SQL 是关于“集合”并将它们组合起来并对结果进行排序。
这个问题似乎是关于两个不同的集合:
1) 有读数的“快照日”。
2) 没有读数的“快照日”。
我添加了额外的列,以便我们可以轻松查看值的来源。
让我们先处理简单的集合:
这是一组“提供”读数。
SELECT dss.SnapShotDay theDay,
'supplied' readingExists,
dss.OperationalUnitNumber,
dss.IsOpen,
dss.StatusDate
FROM dailysnapshot dss
WHERE dss.OperationalUnitNumber IS NOT NULL
结果:
theDay readingExists OperationalUnitNumber IsOpen StatusDate
2014-01-01 supplied 001 1 2014-01-01
2014-01-03 supplied 001 0 2014-01-03
2014-01-05 supplied 001 1 2014-01-05
现在让我们处理一组“缺少读数的日子”。我们需要获取“读数与缺失读数最接近的最近一天”,并假设“当前”缺失日期之前的“最近一天”的值相同。
这听起来很复杂,但事实并非如此。它问:
foreach day without a reading - 给我最接近、更早的有读数的日期,我将使用这些读数。
这里是查询:
SELECT emptyDSS.SnapShotDay,
'missing' readingExists,
maxPrevDSS.OperationalUnitNumber,
maxPrevDSS.IsOpen,
maxPrevDSS.StatusDate
FROM dailysnapshot emptyDSS
INNER JOIN dailysnapshot maxPrevDSS ON maxPrevDSS.SnapShotDay =
(SELECT MAX(dss.SnapShotDay)
FROM dailysnapshot dss
WHERE dss.SnapShotDay < emptyDSS.SnapShotDay
AND dss.OperationalUnitNumber IS NOT NULL)
WHERE emptyDSS.OperationalUnitNumber IS NULL
结果:
SnapShotDay readingExists OperationalUnitNumber IsOpen StatusDate
2014-01-02 missing 001 1 2014-01-01
2014-01-04 missing 001 0 2014-01-03
这与效率无关!它是关于使用最容易理解的 SQL 代码获得正确的“结果集”。我假设数据库引擎会优化查询。如果需要,可以稍后“调整”查询。
我们现在需要组合这两个查询,并以我们需要的方式对结果进行排序。
组合 SQL 查询结果的标准方法是使用集合运算符(联合、交集、减号)。
我们在结果集上使用“union”和“order by”。
这给出了最终查询:
SELECT dss.SnapShotDay theDay,
'supplied' readingExists,
dss.OperationalUnitNumber,
dss.IsOpen,
dss.StatusDate
FROM dailysnapshot dss
WHERE `OperationalUnitNumber` IS NOT NULL
UNION
SELECT emptyDSS.SnapShotDay theDay,
'missing' readingExists,
maxPrevDSS.OperationalUnitNumber,
maxPrevDSS.IsOpen,
maxPrevDSS.StatusDate
FROM dailysnapshot emptyDSS
INNER JOIN dailysnapshot maxPrevDSS ON maxPrevDSS.SnapShotDay =
(SELECT MAX(dss.SnapShotDay)
FROM dailysnapshot dss
WHERE dss.SnapShotDay < emptyDSS.SnapShotDay
AND dss.OperationalUnitNumber IS NOT NULL)
WHERE emptyDSS.OperationalUnitNumber IS NULL
ORDER BY theDay ASC
结果:
theDay readingExists dss.OperationalUnitNumber dss.IsOpen dss.StatusDate
2014-01-01 supplied 001 1 2014-01-01
2014-01-02 missing 001 1 2014-01-01
2014-01-03 supplied 001 0 2014-01-03
2014-01-04 missing 001 0 2014-01-03
2014-01-05 supplied 001 1 2014-01-05
我喜欢这样做。
它应该适用于大多数 SQL 引擎。