Delphi & SQLite: 获取过去 12 个月每月的记录数
Delphi & SQLite: Get the records count per month for the last 12 months
我正在尝试获取过去 12 个月(包括当前月份)按月分组的记录数。
不是当年年初。
我有一个 table 事件和一个字段 WODATE。我可以做到
aFDQuery.Connection := TrackingDBConnection;
aFDQuery.SQL.Clear;
with aFDQuery.SQL do
begin
BeginUpdate;
try
Add('Select MONTH(MAX(WODate)) AS month, COUNT(*) AS count ');
Add('from events where YEAR(WODATE) = 2020 ');
Add('GROUP BY YEAR(WODate), MONTH(WODate) ORDER BY YEAR(WODate), MONTH(WODate) ASC');
finally
EndUpdate;
end;
通过该查询,我只得到了除 0 以外的值的几个月的结果,而且显然只得到了 2020 年的结果
但我想从现在开始的最后 12 个月,即使是这样的 0
[01] 11/2019 12
[02] 12/2019 24
[03] 01/2020 0
[04] 02/2020 12
[05] 03/2020 44
[06] 04/2020 0
[07] 05/2020 21
[08] 06/2020 37
[09] 07/2020 0
[10] 08/2020 15
[11] 09/2020 45
[12] 10/2020 6
我试过了,但出现语法错误
Add('from EVENTS where WODATE >= DATE(NOW, -12 month) ');
ESQLiteNativeException: [FireDAC][Phys][SQLite] ERROR: near "month": syntax error
可能吗?预先感谢您的任何建议
有了 Peter 的回答(见下文),我明白了
2019-11-01 - 2019-11-30 0
2019-12-01 - 2019-12-31 0
2020-01-01 - 2020-01-31 0
2020-02-01 - 2020-02-29 0
2020-03-01 - 2020-03-31 0
2020-04-01 - 2020-04-30 0
2020-05-01 - 2020-05-31 0
2020-06-01 - 2020-06-30 0
2020-07-01 - 2020-07-31 0
2020-08-01 - 2020-08-31 0
2020-09-01 - 2020-09-30 0
2020-10-01 - 2020-10-31 13
这是完美的
非常感谢彼得。你值得拥有比利时啤酒
这不是一个 Delphi 问题,而是 SQL 一个简单的问题。自 version 3.8.3 you can use common table expressions (CTE) and the VALUES
clause。下面我来解释一下。
首先,您可以构建包含 12 个条目的静态日期范围 table,其中每个条目代表过去 12 个月中的一个月,包括当前:
VALUES
(date('now', 'start of month', '-11 month'), date('now', 'start of month', '-10 month', '-1 day')),
(date('now', 'start of month', '-10 month'), date('now', 'start of month', '-9 month', '-1 day')),
(date('now', 'start of month', '-9 month'), date('now', 'start of month', '-8 month', '-1 day')),
(date('now', 'start of month', '-8 month'), date('now', 'start of month', '-7 month', '-1 day')),
(date('now', 'start of month', '-7 month'), date('now', 'start of month', '-6 month', '-1 day')),
(date('now', 'start of month', '-6 month'), date('now', 'start of month', '-5 month', '-1 day')),
(date('now', 'start of month', '-5 month'), date('now', 'start of month', '-4 month', '-1 day')),
(date('now', 'start of month', '-4 month'), date('now', 'start of month', '-3 month', '-1 day')),
(date('now', 'start of month', '-3 month'), date('now', 'start of month', '-2 month', '-1 day')),
(date('now', 'start of month', '-2 month'), date('now', 'start of month', '-1 month', '-1 day')),
(date('now', 'start of month', '-1 month'), date('now', 'start of month', '-1 day')),
(date('now', 'start of month'), date('now', 'start of month', '+1 month', '-1 day'))
这给出(截至当前日期):
StartDate
EndDate
2019-11-01
2019-11-30
2019-12-01
2019-12-31
2020-01-01
2020-01-31
2020-02-01
2020-02-29
2020-03-01
2020-03-31
2020-04-01
2020-04-30
2020-05-01
2020-05-31
2020-06-01
2020-06-30
2020-07-01
2020-07-31
2020-08-01
2020-08-31
2020-09-01
2020-09-30
2020-10-01
2020-10-31
使用 CTE,您可以将您的 events
table 加入到上面的列表中:
WITH DateRanges(StartDate, EndDate) AS (VALUES
(date('now', 'start of month', '-11 month'), date('now', 'start of month', '-10 month', '-1 day')),
(date('now', 'start of month', '-10 month'), date('now', 'start of month', '-9 month', '-1 day')),
(date('now', 'start of month', '-9 month'), date('now', 'start of month', '-8 month', '-1 day')),
(date('now', 'start of month', '-8 month'), date('now', 'start of month', '-7 month', '-1 day')),
(date('now', 'start of month', '-7 month'), date('now', 'start of month', '-6 month', '-1 day')),
(date('now', 'start of month', '-6 month'), date('now', 'start of month', '-5 month', '-1 day')),
(date('now', 'start of month', '-5 month'), date('now', 'start of month', '-4 month', '-1 day')),
(date('now', 'start of month', '-4 month'), date('now', 'start of month', '-3 month', '-1 day')),
(date('now', 'start of month', '-3 month'), date('now', 'start of month', '-2 month', '-1 day')),
(date('now', 'start of month', '-2 month'), date('now', 'start of month', '-1 month', '-1 day')),
(date('now', 'start of month', '-1 month'), date('now', 'start of month', '-1 day')),
(date('now', 'start of month'), date('now', 'start of month', '+1 month', '-1 day'))
)
SELECT
DateRanges.StartDate,
DateRanges.EndDate,
COUNT(Events.ROWID) AS Count
FROM DateRanges
LEFT OUTER JOIN Events ON (DateRanges.StartDate <= Events.WODate) AND (Events.WODate <= DateRanges.EndDate)
GROUP BY
DateRanges.StartDate, DateRanges.EndDate
ORDER BY
DateRanges.StartDate
编辑
我看到您正在努力使用 TFDQuery
执行 SQL,所以我为您做了:
with aFDQuery.SQL do
begin
BeginUpdate;
try
Add('WITH DateRanges(StartDate, EndDate) AS (VALUES');
Add('(date(''now'', ''start of month'', ''-11 month''), date(''now'', ''start of month'', ''-10 month'', ''-1 day'')),');
Add('(date(''now'', ''start of month'', ''-10 month''), date(''now'', ''start of month'', ''-9 month'', ''-1 day'')),');
Add('(date(''now'', ''start of month'', ''-9 month''), date(''now'', ''start of month'', ''-8 month'', ''-1 day'')),');
Add('(date(''now'', ''start of month'', ''-8 month''), date(''now'', ''start of month'', ''-7 month'', ''-1 day'')),');
Add('(date(''now'', ''start of month'', ''-7 month''), date(''now'', ''start of month'', ''-6 month'', ''-1 day'')),');
Add('(date(''now'', ''start of month'', ''-6 month''), date(''now'', ''start of month'', ''-5 month'', ''-1 day'')),');
Add('(date(''now'', ''start of month'', ''-5 month''), date(''now'', ''start of month'', ''-4 month'', ''-1 day'')),');
Add('(date(''now'', ''start of month'', ''-4 month''), date(''now'', ''start of month'', ''-3 month'', ''-1 day'')),');
Add('(date(''now'', ''start of month'', ''-3 month''), date(''now'', ''start of month'', ''-2 month'', ''-1 day'')),');
Add('(date(''now'', ''start of month'', ''-2 month''), date(''now'', ''start of month'', ''-1 month'', ''-1 day'')),');
Add('(date(''now'', ''start of month'', ''-1 month''), date(''now'', ''start of month'', ''-1 day'')),');
Add('(date(''now'', ''start of month''), date(''now'', ''start of month'', ''+1 month'', ''-1 day'')))');
Add('SELECT DateRanges.StartDate, DateRanges.EndDate, COUNT(Events.ROWID) AS Count');
Add('FROM DateRanges LEFT OUTER JOIN Events ON (DateRanges.StartDate <= Events.WODate) AND (Events.WODate <= DateRanges.EndDate)');
Add('GROUP BY DateRanges.StartDate, DateRanges.EndDate');
Add('ORDER BY DateRanges.StartDate');
finally
EndUpdate;
end;
end;
用户 Peter Wolf 回答我设计了这个小修改回答 - IMO - 更好的问题:
WITH DateRanges(StartDate, EndDate) AS (VALUES
(date('now', 'start of month', '-11 month'), date('now', 'start of month', '-10 month', '-1 day')),
(date('now', 'start of month', '-10 month'), date('now', 'start of month', '-9 month', '-1 day')),
(date('now', 'start of month', '-9 month'), date('now', 'start of month', '-8 month', '-1 day')),
(date('now', 'start of month', '-8 month'), date('now', 'start of month', '-7 month', '-1 day')),
(date('now', 'start of month', '-7 month'), date('now', 'start of month', '-6 month', '-1 day')),
(date('now', 'start of month', '-6 month'), date('now', 'start of month', '-5 month', '-1 day')),
(date('now', 'start of month', '-5 month'), date('now', 'start of month', '-4 month', '-1 day')),
(date('now', 'start of month', '-4 month'), date('now', 'start of month', '-3 month', '-1 day')),
(date('now', 'start of month', '-3 month'), date('now', 'start of month', '-2 month', '-1 day')),
(date('now', 'start of month', '-2 month'), date('now', 'start of month', '-1 month', '-1 day')),
(date('now', 'start of month', '-1 month'), date('now', 'start of month', '-1 day')),
(date('now', 'start of month'), date('now', 'start of month', '+1 month', '-1 day'))
)
SELECT
strftime('%m/%Y', DateRanges.StartDate) as Month,
COUNT(Events.ROWID) AS Count
FROM DateRanges
LEFT OUTER JOIN Events ON (DateRanges.StartDate <= Date(Events.WODate)) AND (Events.WODate <= Date(DateRanges.EndDate))
GROUP BY
DateRanges.StartDate, DateRanges.EndDate
ORDER BY
DateRanges.StartDate
我正在尝试获取过去 12 个月(包括当前月份)按月分组的记录数。 不是当年年初。
我有一个 table 事件和一个字段 WODATE。我可以做到
aFDQuery.Connection := TrackingDBConnection;
aFDQuery.SQL.Clear;
with aFDQuery.SQL do
begin
BeginUpdate;
try
Add('Select MONTH(MAX(WODate)) AS month, COUNT(*) AS count ');
Add('from events where YEAR(WODATE) = 2020 ');
Add('GROUP BY YEAR(WODate), MONTH(WODate) ORDER BY YEAR(WODate), MONTH(WODate) ASC');
finally
EndUpdate;
end;
通过该查询,我只得到了除 0 以外的值的几个月的结果,而且显然只得到了 2020 年的结果
但我想从现在开始的最后 12 个月,即使是这样的 0
[01] 11/2019 12
[02] 12/2019 24
[03] 01/2020 0
[04] 02/2020 12
[05] 03/2020 44
[06] 04/2020 0
[07] 05/2020 21
[08] 06/2020 37
[09] 07/2020 0
[10] 08/2020 15
[11] 09/2020 45
[12] 10/2020 6
我试过了,但出现语法错误
Add('from EVENTS where WODATE >= DATE(NOW, -12 month) ');
ESQLiteNativeException: [FireDAC][Phys][SQLite] ERROR: near "month": syntax error
可能吗?预先感谢您的任何建议
有了 Peter 的回答(见下文),我明白了
2019-11-01 - 2019-11-30 0
2019-12-01 - 2019-12-31 0
2020-01-01 - 2020-01-31 0
2020-02-01 - 2020-02-29 0
2020-03-01 - 2020-03-31 0
2020-04-01 - 2020-04-30 0
2020-05-01 - 2020-05-31 0
2020-06-01 - 2020-06-30 0
2020-07-01 - 2020-07-31 0
2020-08-01 - 2020-08-31 0
2020-09-01 - 2020-09-30 0
2020-10-01 - 2020-10-31 13
这是完美的 非常感谢彼得。你值得拥有比利时啤酒
这不是一个 Delphi 问题,而是 SQL 一个简单的问题。自 version 3.8.3 you can use common table expressions (CTE) and the VALUES
clause。下面我来解释一下。
首先,您可以构建包含 12 个条目的静态日期范围 table,其中每个条目代表过去 12 个月中的一个月,包括当前:
VALUES
(date('now', 'start of month', '-11 month'), date('now', 'start of month', '-10 month', '-1 day')),
(date('now', 'start of month', '-10 month'), date('now', 'start of month', '-9 month', '-1 day')),
(date('now', 'start of month', '-9 month'), date('now', 'start of month', '-8 month', '-1 day')),
(date('now', 'start of month', '-8 month'), date('now', 'start of month', '-7 month', '-1 day')),
(date('now', 'start of month', '-7 month'), date('now', 'start of month', '-6 month', '-1 day')),
(date('now', 'start of month', '-6 month'), date('now', 'start of month', '-5 month', '-1 day')),
(date('now', 'start of month', '-5 month'), date('now', 'start of month', '-4 month', '-1 day')),
(date('now', 'start of month', '-4 month'), date('now', 'start of month', '-3 month', '-1 day')),
(date('now', 'start of month', '-3 month'), date('now', 'start of month', '-2 month', '-1 day')),
(date('now', 'start of month', '-2 month'), date('now', 'start of month', '-1 month', '-1 day')),
(date('now', 'start of month', '-1 month'), date('now', 'start of month', '-1 day')),
(date('now', 'start of month'), date('now', 'start of month', '+1 month', '-1 day'))
这给出(截至当前日期):
StartDate | EndDate |
---|---|
2019-11-01 | 2019-11-30 |
2019-12-01 | 2019-12-31 |
2020-01-01 | 2020-01-31 |
2020-02-01 | 2020-02-29 |
2020-03-01 | 2020-03-31 |
2020-04-01 | 2020-04-30 |
2020-05-01 | 2020-05-31 |
2020-06-01 | 2020-06-30 |
2020-07-01 | 2020-07-31 |
2020-08-01 | 2020-08-31 |
2020-09-01 | 2020-09-30 |
2020-10-01 | 2020-10-31 |
使用 CTE,您可以将您的 events
table 加入到上面的列表中:
WITH DateRanges(StartDate, EndDate) AS (VALUES
(date('now', 'start of month', '-11 month'), date('now', 'start of month', '-10 month', '-1 day')),
(date('now', 'start of month', '-10 month'), date('now', 'start of month', '-9 month', '-1 day')),
(date('now', 'start of month', '-9 month'), date('now', 'start of month', '-8 month', '-1 day')),
(date('now', 'start of month', '-8 month'), date('now', 'start of month', '-7 month', '-1 day')),
(date('now', 'start of month', '-7 month'), date('now', 'start of month', '-6 month', '-1 day')),
(date('now', 'start of month', '-6 month'), date('now', 'start of month', '-5 month', '-1 day')),
(date('now', 'start of month', '-5 month'), date('now', 'start of month', '-4 month', '-1 day')),
(date('now', 'start of month', '-4 month'), date('now', 'start of month', '-3 month', '-1 day')),
(date('now', 'start of month', '-3 month'), date('now', 'start of month', '-2 month', '-1 day')),
(date('now', 'start of month', '-2 month'), date('now', 'start of month', '-1 month', '-1 day')),
(date('now', 'start of month', '-1 month'), date('now', 'start of month', '-1 day')),
(date('now', 'start of month'), date('now', 'start of month', '+1 month', '-1 day'))
)
SELECT
DateRanges.StartDate,
DateRanges.EndDate,
COUNT(Events.ROWID) AS Count
FROM DateRanges
LEFT OUTER JOIN Events ON (DateRanges.StartDate <= Events.WODate) AND (Events.WODate <= DateRanges.EndDate)
GROUP BY
DateRanges.StartDate, DateRanges.EndDate
ORDER BY
DateRanges.StartDate
编辑
我看到您正在努力使用 TFDQuery
执行 SQL,所以我为您做了:
with aFDQuery.SQL do
begin
BeginUpdate;
try
Add('WITH DateRanges(StartDate, EndDate) AS (VALUES');
Add('(date(''now'', ''start of month'', ''-11 month''), date(''now'', ''start of month'', ''-10 month'', ''-1 day'')),');
Add('(date(''now'', ''start of month'', ''-10 month''), date(''now'', ''start of month'', ''-9 month'', ''-1 day'')),');
Add('(date(''now'', ''start of month'', ''-9 month''), date(''now'', ''start of month'', ''-8 month'', ''-1 day'')),');
Add('(date(''now'', ''start of month'', ''-8 month''), date(''now'', ''start of month'', ''-7 month'', ''-1 day'')),');
Add('(date(''now'', ''start of month'', ''-7 month''), date(''now'', ''start of month'', ''-6 month'', ''-1 day'')),');
Add('(date(''now'', ''start of month'', ''-6 month''), date(''now'', ''start of month'', ''-5 month'', ''-1 day'')),');
Add('(date(''now'', ''start of month'', ''-5 month''), date(''now'', ''start of month'', ''-4 month'', ''-1 day'')),');
Add('(date(''now'', ''start of month'', ''-4 month''), date(''now'', ''start of month'', ''-3 month'', ''-1 day'')),');
Add('(date(''now'', ''start of month'', ''-3 month''), date(''now'', ''start of month'', ''-2 month'', ''-1 day'')),');
Add('(date(''now'', ''start of month'', ''-2 month''), date(''now'', ''start of month'', ''-1 month'', ''-1 day'')),');
Add('(date(''now'', ''start of month'', ''-1 month''), date(''now'', ''start of month'', ''-1 day'')),');
Add('(date(''now'', ''start of month''), date(''now'', ''start of month'', ''+1 month'', ''-1 day'')))');
Add('SELECT DateRanges.StartDate, DateRanges.EndDate, COUNT(Events.ROWID) AS Count');
Add('FROM DateRanges LEFT OUTER JOIN Events ON (DateRanges.StartDate <= Events.WODate) AND (Events.WODate <= DateRanges.EndDate)');
Add('GROUP BY DateRanges.StartDate, DateRanges.EndDate');
Add('ORDER BY DateRanges.StartDate');
finally
EndUpdate;
end;
end;
用户 Peter Wolf 回答我设计了这个小修改回答 - IMO - 更好的问题:
WITH DateRanges(StartDate, EndDate) AS (VALUES
(date('now', 'start of month', '-11 month'), date('now', 'start of month', '-10 month', '-1 day')),
(date('now', 'start of month', '-10 month'), date('now', 'start of month', '-9 month', '-1 day')),
(date('now', 'start of month', '-9 month'), date('now', 'start of month', '-8 month', '-1 day')),
(date('now', 'start of month', '-8 month'), date('now', 'start of month', '-7 month', '-1 day')),
(date('now', 'start of month', '-7 month'), date('now', 'start of month', '-6 month', '-1 day')),
(date('now', 'start of month', '-6 month'), date('now', 'start of month', '-5 month', '-1 day')),
(date('now', 'start of month', '-5 month'), date('now', 'start of month', '-4 month', '-1 day')),
(date('now', 'start of month', '-4 month'), date('now', 'start of month', '-3 month', '-1 day')),
(date('now', 'start of month', '-3 month'), date('now', 'start of month', '-2 month', '-1 day')),
(date('now', 'start of month', '-2 month'), date('now', 'start of month', '-1 month', '-1 day')),
(date('now', 'start of month', '-1 month'), date('now', 'start of month', '-1 day')),
(date('now', 'start of month'), date('now', 'start of month', '+1 month', '-1 day'))
)
SELECT
strftime('%m/%Y', DateRanges.StartDate) as Month,
COUNT(Events.ROWID) AS Count
FROM DateRanges
LEFT OUTER JOIN Events ON (DateRanges.StartDate <= Date(Events.WODate)) AND (Events.WODate <= Date(DateRanges.EndDate))
GROUP BY
DateRanges.StartDate, DateRanges.EndDate
ORDER BY
DateRanges.StartDate