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
我为下面的最后一部分“使用递归”而苦恼。当然,我可以使用 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