WITH RECURSIVE 循环遍历数据库中的每一天和每个日期之间的 SUM 数

WITH RECURSIVE looping through every day in the database and SUM number between two dates for each

我为下面的最后一部分“使用递归”而苦恼。当然,我可以使用 C# 遍历数据库中的每一天的 TimestampOrigin。这将意味着数百次相同的查询。但是使用“with recursive”的一个查询是可能的。

测试数据:

CREATE TABLE tblData(
  Id INT, ComputerName TEXT, TimestampOrigin TEXT, Timestamp TEXT, Number INT
);

DELETE FROM tblData;

INSERT INTO tblData VALUES (1, "Computer1", '2021-02-10 12:00:00', '2021-02-27 12:00:00', 35);
INSERT INTO tblData VALUES (2, "Computer2", '2021-02-10 12:00:00', '2021-02-27 12:00:00', 24);
INSERT INTO tblData VALUES (3, "Computer3", '2021-02-09 12:00:00', '2021-02-26 12:00:00', 23);
INSERT INTO tblData VALUES (3, "Computer4", '2021-02-09 12:00:00', '2021-02-26 12:00:00', null);
INSERT INTO tblData VALUES (4, "Computer5", '2021-02-08 12:00:00', '2021-02-25 12:00:00', 7);
INSERT INTO tblData VALUES (5, "Computer6", '2021-02-08 12:00:00', '2021-02-25 12:00:00', 0);
INSERT INTO tblData VALUES (7, "Computer7", '2021-02-07 12:00:00', '2021-02-24 12:00:00', 9);

按 TimestampOrigin 分组的查询:

SELECT DATE(TimestampOrigin) AS TimestampOrigin,
SUM(CASE WHEN Number < 1 THEN 1 ELSE 0 END) AS Less1,
SUM(CASE WHEN Number >= 0 AND Number < 10 THEN 1 ELSE 0 END) AS Less10,
SUM(CASE WHEN Number >= 10 AND Number < 25 THEN 1 ELSE 0 END) AS Less25
FROM tblData WHERE Number NOT NULL GROUP BY DATE(TimestampOrigin) ORDER BY TimestampOrigin DESC

我需要的是每天当前时间戳的总和,即当天+17 天。以 2021-02-08 日为例,TimestampOrigin 为 2021-02-08 到 2021-02-08 +17 天的所有行的总和(时间戳列)。 不知道是否真的需要 TimestampOrigin +17 天的中午时间的额外列 Timestamp。但是超时查询是我在项目一开始就创建它的原因。

SELECT DATE(TimestampOrigin) AS TimestampOrigin,
SUM(CASE WHEN Number < 1 THEN 1 ELSE 0 END) AS Less1,
SUM(CASE WHEN Number >= 0 AND Number < 10 THEN 1 ELSE 0 END) AS Less10,
SUM(CASE WHEN Number >= 10 AND Number < 25 THEN 1 ELSE 0 END) AS Less25
FROM tblData WHERE Number NOT NULL AND DATE(TimestampOrigin) >= DATE('2021-02-08') AND DATE(TimestampOrigin) <= DATE('2021-02-08', '+17 day')

我认为“使用递归”是正确的方法,而不是对每一天和总和执行上述查询数百次。但到目前为止无法使其工作。在哪里添加 17 天?

WITH RECURSIVE cte AS (
    SELECT Id, ComputerName, Timestamp, DATE(Timestamp,'+1 day') totime, Number, TimestampOrigin
    FROM tblData
    UNION ALL
    SELECT Id, ComputerName, DATE(Timestamp,'+1 day'), DATE(totime,'+1 day'), Number, TimestampOrigin
    FROM cte
    WHERE Number NOT NULL AND DATE(Timestamp,'+1 day') < DATE('2021-02-11')
)
    SELECT DATE(TimestampOrigin), 
    SUM(CASE WHEN Number < 1 THEN 1 ELSE 0 END) AS Less1,
    SUM(CASE WHEN Number >= 0 AND Number < 10 THEN 1 ELSE 0 END) AS Less10,
    SUM(CASE WHEN Number >= 10 AND Number < 25 THEN 1 ELSE 0 END) AS Less25
FROM cte GROUP BY DATE(TimestampOrigin) ORDER BY DATE(TimestampOrigin) DESC

预期结果是(就像我 运行 测试数据中 4 天的每一天的上述查询):

不需要递归 CTE。
根据您的条件将不同的 TimestampOrigin 加入 table 并聚合:

SELECT t1.TimestampOrigin,
       SUM(t2.Number < 1) AS Less1,
       SUM(t2.Number >= 0 AND t2.Number < 10) AS Less10,
       SUM(t2.Number >= 10 AND t2.Number < 25) AS Less25
FROM (SELECT DISTINCT DATE(TimestampOrigin) TimestampOrigin FROM tblData) t1 
INNER JOIN tblData t2
ON DATE(t2.TimestampOrigin) BETWEEN t1.TimestampOrigin AND DATE(t1.TimestampOrigin, '+17 days')
GROUP BY t1.TimestampOrigin 
ORDER BY t1.TimestampOrigin DESC

参见demo
结果:

TimestampOrigin Less1 Less10 Less25
2021-02-10 0 0 1
2021-02-09 0 0 2
2021-02-08 1 2 2
2021-02-07 1 3 2

结果错误。我发现我最初的查询是错误的。但是使用@forpas 的解决方案,它最终起作用了。

初始单个查询

    SELECT 
        SUM(Number < 1) AS Less1,
        SUM(Number >= 1 AND Number < 10) AS Less10,
        SUM(Number >= 10 AND Number < 25) AS Less25
    FROM tblPCHardwareInformation WHERE UniqueInventoryKey IN
    (
        SELECT UniqueInventoryKey FROM tblPCHardwareInformation WHERE Number NOT NULL AND DATE(Timestamp) BETWEEN DATE('2020-10-09') AND DATE('2020-10-09', '+17 day') GROUP BY ComputerName ORDER BY Timestamp DESC
    )

结果:

SELECT t1.TimestampOrigin,
       SUM(t2.Number < 1) AS Less1,
       SUM(t2.Number >= 1 AND t2.Number < 10) AS Less10,
       SUM(t2.Number >= 10 AND t2.Number < 25) AS Less25
FROM (SELECT DISTINCT DATE(TimestampOrigin) TimestampOrigin FROM tblPCHardwareInformation) t1 
INNER JOIN tblPCHardwareInformation t2
ON UniqueInventoryKey IN
(
    SELECT UniqueInventoryKey FROM tblPCHardwareInformation WHERE Number NOT NULL AND DATE(Timestamp) BETWEEN DATE(t1.TimestampOrigin) AND DATE(t1.TimestampOrigin, '+17 day') GROUP BY ComputerName ORDER BY Timestamp DESC
)
GROUP BY t1.TimestampOrigin 
ORDER BY t1.TimestampOrigin DESC