SQL 查询以计算日期范围内的项目?
SQL Query to Count Items Within Date Range?
首先,我现在所知道的足以让自己陷入麻烦。我正在为 AS/400 系统编写查询。我有一个包含开始日期和结束日期的文件。我想要做的是创建一个查询,该查询可以计算在某个日期范围内打开了多少行项目。 (对于我的应用程序,打开定义为:DATE > START_DATE
AND (DATE <= END_DATE OR END_DATE = '0'
))。我可以通过手动设置 "DATE" 获得此功能,但我正在尝试返回并从历史上批量提取此信息。我遇到的问题是 运行 这个查询针对日期列表。我想要的是输入历史间隔(比如CURRENT_DATE - 5
)并输出:
Date Open
20200206 30,000
20200207 31,000
20200210 29,675
20200211 31,375
20200212 32,000
我用于 'one-day-at-a-time' 查询的内容:
SELECT
COUNT(*)
FROM
MYFILE
WHERE
START_DATE < '20200210'
AND (
END_DATE >= '20200210'
OR END_DATE = '0'
)
这很好用,但很耗时。从这里我不知道如何过渡到所需的输出......或者即使可能......但它会加快我的速度。提前致谢。
P.S。欢迎任何帮助,如果您知道如何在 mySQL 等中完成此操作,请分享。我可以把它和 运行 结合起来,让它专门为 AS/400 工作。我就是这样走到现在的。
****************** 编辑澄清
1. 当前代码
提供的当前代码是我所拥有的。我不知道从哪里开始
关于我的要求。
2. 示例数据:
Line Item START_DATE END_DATE
1 20200206 20200210
2 20200207 20200210
3 20200207 20200207
- 预期输出:
DATE COUNT
20200205 0
20200206 0
20200207 1
20200210 2
20200211 0
- DBMS 我更新了标签以包含 DB2。 5. 我认为 GROUP BY 行不通。
基本上我正在寻找以迭代式方式计算的结果。从我的 python/java 背景来看,这对我来说很有意义。我不是在寻找 5 天前打开的所有内容,我想从 5 天前开始计算这 5 天中每一天打开的订单项数量。如果这实际上可以通过 GROUP 实现,请详细说明并告诉我我的方法的错误。同时,我要开始搞乱分组了。
请试试这个:
SELECT COUNT(*) FROM MYFILE WHERE (START_DATE < '20200205' AND (END_DATE >= '20200210' OR END_DATE = '0')) GROUP BY DATE_FORMAT(START_DATE , '%Y%m%d')
听起来像是对 group by
语句的简单使用,但您没有说明要分组的列,只是一个日期,我假设 START_DATE
我不知道 AS/400 SQL 所以我会有点抽象并假设 CURRENT_DATE() returns 当前日期语言环境。 RDBMS 在这方面有所不同。
鉴于这些假设,类似以下内容应该有所帮助:
SELECT
START_DATE as DATE,
COUNT(*) as OPEN
FROM
MYFILE
WHERE
START_DATE >= (CURRENT_DATE() - 5)
AND (
END_DATE >= (CURRENT_DATE() - 5)
OR END_DATE = '0'
)
GROUP BY
START_DATE
逆透视数据并使用 window 函数进行聚合。这是想法:
with se as (
select dte, sum(ins) as ins, sum(outs) as outs
from ((select start_date as dte, count(*) as ins, 0 as outs
from t
) union all
(select end_date, 0, count(*) as outs
from t
)
)
select dte, ins, outs,
(sum(sum(ins)) over (order by dte) -
sum(sum(outs)) over (order by dte)
)
from se
order by dte;
这会将给定日期的所有开始次数相加并减去结束次数。
备注:
- 如果要按日期过滤,请将过滤逻辑放在 outer 查询中。
- 这假设所有日期都有效。如果某些日期比较特殊,您需要在
order by
. 中考虑到这一点
- 这不包括离开当天的人数。如果要计算它们,只需将 1 天添加到子查询中的
end_date
。
下面是一个返回给定日期和给定日期之间的连续日期的查询 - 5 天。当然,您可以使用 CURRENT DATE
而不是这个常量。
WITH T (DT) AS
(
VALUES DATE('2020-02-13') - 5 DAYS
UNION ALL
SELECT DT + 1 DAY
FROM T
WHERE DT < DATE('2020-02-13')
)
SELECT DT FROM T;
结果是:
|DT |
|----------|
|2020-02-08|
|2020-02-09|
|2020-02-10|
|2020-02-11|
|2020-02-12|
|2020-02-13|
这种 "virtual table" 的进一步用法是显而易见的:您可以 LEFT JOIN
它与 B.START_DATE < DEC(TO_CHAR(T.DT, 'YYYYMMDD'), 8) AND DEC(TO_CHAR(T.DT, 'YYYYMMDD'), 8) <= B.END_DATE
上的基础 table 一起将结果按 T.DT
分组。
首先,我现在所知道的足以让自己陷入麻烦。我正在为 AS/400 系统编写查询。我有一个包含开始日期和结束日期的文件。我想要做的是创建一个查询,该查询可以计算在某个日期范围内打开了多少行项目。 (对于我的应用程序,打开定义为:DATE > START_DATE
AND (DATE <= END_DATE OR END_DATE = '0'
))。我可以通过手动设置 "DATE" 获得此功能,但我正在尝试返回并从历史上批量提取此信息。我遇到的问题是 运行 这个查询针对日期列表。我想要的是输入历史间隔(比如CURRENT_DATE - 5
)并输出:
Date Open
20200206 30,000
20200207 31,000
20200210 29,675
20200211 31,375
20200212 32,000
我用于 'one-day-at-a-time' 查询的内容:
SELECT
COUNT(*)
FROM
MYFILE
WHERE
START_DATE < '20200210'
AND (
END_DATE >= '20200210'
OR END_DATE = '0'
)
这很好用,但很耗时。从这里我不知道如何过渡到所需的输出......或者即使可能......但它会加快我的速度。提前致谢。
P.S。欢迎任何帮助,如果您知道如何在 mySQL 等中完成此操作,请分享。我可以把它和 运行 结合起来,让它专门为 AS/400 工作。我就是这样走到现在的。
****************** 编辑澄清 1. 当前代码 提供的当前代码是我所拥有的。我不知道从哪里开始 关于我的要求。 2. 示例数据:
Line Item START_DATE END_DATE
1 20200206 20200210
2 20200207 20200210
3 20200207 20200207
- 预期输出:
DATE COUNT
20200205 0
20200206 0
20200207 1
20200210 2
20200211 0
- DBMS 我更新了标签以包含 DB2。 5. 我认为 GROUP BY 行不通。
基本上我正在寻找以迭代式方式计算的结果。从我的 python/java 背景来看,这对我来说很有意义。我不是在寻找 5 天前打开的所有内容,我想从 5 天前开始计算这 5 天中每一天打开的订单项数量。如果这实际上可以通过 GROUP 实现,请详细说明并告诉我我的方法的错误。同时,我要开始搞乱分组了。
请试试这个:
SELECT COUNT(*) FROM MYFILE WHERE (START_DATE < '20200205' AND (END_DATE >= '20200210' OR END_DATE = '0')) GROUP BY DATE_FORMAT(START_DATE , '%Y%m%d')
听起来像是对 group by
语句的简单使用,但您没有说明要分组的列,只是一个日期,我假设 START_DATE
我不知道 AS/400 SQL 所以我会有点抽象并假设 CURRENT_DATE() returns 当前日期语言环境。 RDBMS 在这方面有所不同。
鉴于这些假设,类似以下内容应该有所帮助:
SELECT
START_DATE as DATE,
COUNT(*) as OPEN
FROM
MYFILE
WHERE
START_DATE >= (CURRENT_DATE() - 5)
AND (
END_DATE >= (CURRENT_DATE() - 5)
OR END_DATE = '0'
)
GROUP BY
START_DATE
逆透视数据并使用 window 函数进行聚合。这是想法:
with se as (
select dte, sum(ins) as ins, sum(outs) as outs
from ((select start_date as dte, count(*) as ins, 0 as outs
from t
) union all
(select end_date, 0, count(*) as outs
from t
)
)
select dte, ins, outs,
(sum(sum(ins)) over (order by dte) -
sum(sum(outs)) over (order by dte)
)
from se
order by dte;
这会将给定日期的所有开始次数相加并减去结束次数。
备注:
- 如果要按日期过滤,请将过滤逻辑放在 outer 查询中。
- 这假设所有日期都有效。如果某些日期比较特殊,您需要在
order by
. 中考虑到这一点
- 这不包括离开当天的人数。如果要计算它们,只需将 1 天添加到子查询中的
end_date
。
下面是一个返回给定日期和给定日期之间的连续日期的查询 - 5 天。当然,您可以使用 CURRENT DATE
而不是这个常量。
WITH T (DT) AS
(
VALUES DATE('2020-02-13') - 5 DAYS
UNION ALL
SELECT DT + 1 DAY
FROM T
WHERE DT < DATE('2020-02-13')
)
SELECT DT FROM T;
结果是:
|DT |
|----------|
|2020-02-08|
|2020-02-09|
|2020-02-10|
|2020-02-11|
|2020-02-12|
|2020-02-13|
这种 "virtual table" 的进一步用法是显而易见的:您可以 LEFT JOIN
它与 B.START_DATE < DEC(TO_CHAR(T.DT, 'YYYYMMDD'), 8) AND DEC(TO_CHAR(T.DT, 'YYYYMMDD'), 8) <= B.END_DATE
上的基础 table 一起将结果按 T.DT
分组。