SQL查询来计算日期范围内的项目?

Posted

技术标签:

【中文标题】SQL查询来计算日期范围内的项目?【英文标题】:SQL Query to Count Items Within Date Range? 【发布时间】:2020-02-12 16:20:19 【问题描述】:

首先,我知道在这一点上足以让自己陷入困境。我正在为 AS/400 系统编写查询。我有一个包含开始日期和结束日期的文件。我想要做的是创建一个查询,可以计算在某个日期范围内打开了多少行项目。 (对于我的应用程序打开定义为:DATE > START_DATE AND (DATE <= END_DATE OR END_DATE = '0'))。我可以手动设置“日期”,但我正试图返回并从历史上批量提取这些信息。我遇到的问题是让它针对日期列表运行此查询。我想要的是输入历史间隔(比如CURRENT_DATE - 5)并输出:

Date             Open
20200206         30,000
20200207         31,000
20200210         29,675
20200211         31,375
20200212         32,000

我用于“一次一天”的查询:

SELECT
        COUNT(*) 
    FROM
        MYFILE
    WHERE 
        START_DATE < '20200210' 
    AND (
            END_DATE >= '20200210' 
        OR  END_DATE = '0'
        )

这很好用,但很耗时。从这里我不知道如何转换到所需的输出......或者即使有可能......但它会加快我的速度。提前致谢。

附:欢迎任何帮助,如果您知道如何在 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 实际上可以做到这一点,请详细说明并向我展示我的方式的错误。与此同时,我将开始为此进行分组。

【问题讨论】:

嗨,欢迎来到 Stack Overflow。请阅读***.com/help/minimal-reproducible-example 和***.com/help/how-to-ask。在这个示例中,我们需要查看您当前的代码,示例数据至关重要。此外,查看您的代码产生的结果与您的预期结果是非常有益的。请参阅:meta.***.com/questions/271055/…。另外,您使用的是什么DBMS?请用那个标记你的问题(我想你提到了mySQL 如果我没记错的话,AS/400 是 IBM 的 DB2 正确吗?如果是这样的话,你能用 DB2 更新问题标签吗? 【参考方案1】:

下面是一个查询,返回给定日期和给定日期之间的连续日期 - 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|

这种“虚拟表”的进一步使用是显而易见的:您可以将LEFT JOINB.START_DATE &lt; DEC(TO_CHAR(T.DT, 'YYYYMMDD'), 8) AND DEC(TO_CHAR(T.DT, 'YYYYMMDD'), 8) &lt;= B.END_DATE 上的基表一起按T.DT 分组结果。

【讨论】:

SELECT M.MY_DAY,COUNT(*) FROM (SELECT DISTINCT(START_DATE) AS MY_DAY FROM MYFILE WHERE START_DATE >= REPLACE(CHAR(CURRENT DATE - 5 DAY, ISO),'-',' ') ORDER BY START_DATE) AS M LEFT JOIN MYFILE P ON M.MY_DAY > P.START_DATE AND (M.MY_DAY 这是最后的查询。谢谢你的帮助,我不知道条件加入可以这样使用。我投了你一票,但我太新了,我的选票无法计算。【参考方案2】:

请试试这个:

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')

【讨论】:

【参考方案3】:

听起来像是group by 语句的简单用法,但你没有说明你是按哪一列分组的,只是一个日期,我假设为 START_DATE

我不知道 AS/400 SQL,所以我将稍微抽象一点,并假设 CURRENT_DATE() 返回您所在地区的当前日期。 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

【讨论】:

【参考方案4】:

取消透视数据并使用窗口函数进行聚合。思路如下:

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 中考虑到这一点。 这不计算某人离开的那天。如果要计算它们,只需在子查询中的 end_date 中添加 1 天即可。

【讨论】:

以上是关于SQL查询来计算日期范围内的项目?的主要内容,如果未能解决你的问题,请参考以下文章

SQL - 显示给定范围内的所有日期,并使用数据库中的时间戳计算该日期有多少帖子

SQL 如何查询日期在一定范围内的数据

SQL在where语句中使用日期范围的选择子查询来确定该日期范围内的最大值

如何在 SQL 中针对事务表计算一段时间内的覆盖日期?

选择日期范围,根据关闭条件计算范围内的多条记录,按班次分组

sql 查询时间、日期范围内的数据