如何生成 sysdate-30 和 sysdate+30 之间的所有日期列表?

Posted

技术标签:

【中文标题】如何生成 sysdate-30 和 sysdate+30 之间的所有日期列表?【英文标题】:How to generate list of all dates between sysdate-30 and sysdate+30? 【发布时间】:2012-02-06 20:33:25 【问题描述】:

目的和我到目前为止所做的事情

我正在尝试创建一个视图来检查丢失的劳动力交易。该视图将被提供给 Crystal 报表。

在这种情况下,视图应获取 sysdate+30 和 sysdate -30 之间的所有日期,然后应将每个这些日期的在职员工的所有劳动记录留在外部联接。然后它会计算每个员工在每个日期的劳务交易次数。

这将传递到 Crystal Report,它将根据特定日期范围(在视图的 +/- 30 范围内)进行过滤。从那里开始,Crystal 中每个员工的所有天数将汇总,并且员工将显示哪些交易为零。

问题

在没有吐出每个日期的列表的情况下,最初,我在每个日期都使用劳动力交易,但有些没有任何日期的计数。这些人显示零小时的空交易日期。这表明他们在整个期间不收费,这是有道理的。

但是,当 Crystal 对该数据进行过滤并选择一个范围时,我相信它会忽略这些空值,因此不允许我展示所有没有时间提交的人。

问题

有没有办法在视图中执行相当于“选择 (sysdate+30) 和 (sysdate-30) 之间的每个日期”的方法,以便我可以一直使用它来比较?

SQL(供参考)

SELECT QUERY.LABORRECLABORCODE
       , QUERY.LABORRECEMPLOYEENUM
       , QUERY.PERSONRECDISPLAYNAME
       , QUERY.TRANSSTARTDATE
       , COUNT(TRANSROWSTAMP) AS ROWCOUNT
FROM   (SELECT *
        FROM  (SELECT LABOR.LABORCODE      AS LABORRECLABORCODE
                      , LABOR.LA20         AS LABORRECEMPLOYEENUM
                      , PERSON.DISPLAYNAME AS PERSONRECDISPLAYNAME
               FROM   LABOR
                      LEFT OUTER JOIN PERSON
                        ON ( LABOR.LABORCODE = PERSON.PERSONID )
               WHERE  LABOR.STATUS = 'ACTIVE'
                  AND LABOR.LA20 IS NOT NULL
                  AND PERSON.DISPLAYNAME IS NOT NULL
                  AND LOWER(PERSON.DISPLAYNAME) NOT LIKE '%kimball%'
                  AND LOWER(PERSON.DISPLAYNAME) NOT LIKE '%electrico%'
                  AND LOWER(PERSON.DISPLAYNAME) NOT LIKE '%misc labor cost adj%'
                  AND LOWER(PERSON.DISPLAYNAME) NOT LIKE '%brossoit%'
                  AND LOWER(PERSON.DISPLAYNAME) NOT LIKE '%brossiot%')PERSONINFO
              LEFT OUTER JOIN (SELECT STARTDATE   AS TRANSSTARTDATE
                                      , LABORCODE AS TRANSLABORCODE
                                      , ROWSTAMP  AS TRANSROWSTAMP
                               FROM   LABTRANS
                               WHERE  STARTDATE BETWEEN ( SYSDATE - 30 ) AND ( SYSDATE + 30 ))LABTRANSLIMITED
                ON ( PERSONINFO.LABORRECLABORCODE = LABTRANSLIMITED.TRANSLABORCODE ))QUERY
GROUP  BY LABORRECLABORCODE
          , TRANSSTARTDATE
          , LABORRECEMPLOYEENUM
          , PERSONRECDISPLAYNAME
ORDER  BY LABORRECLABORCODE
          , TRANSSTARTDATE
; 

【问题讨论】:

【参考方案1】:
select trunc(sysdate)+31-level from dual connect by level <=61

这是生成任意值列表的好方法。

【讨论】:

【参考方案2】:

或者另一种方法:选择一个有很多行的表

select sysdate+30 - rownum from user_objects where rownum<61

【讨论】:

【参考方案3】:

为了满足我在一个范围内是 sysdate -30 和 sysdate + 30 的要求,这似乎是目前最优雅的处理方式:

SELECT *
FROM   (SELECT TRUNC(SYSDATE - ROWNUM) DT
        FROM   DUAL
        CONNECT BY ROWNUM < 31
        UNION
        SELECT TRUNC(SYSDATE + ROWNUM) DT
        FROM   DUAL
        CONNECT BY ROWNUM < 31)DATERANGE; 

我使用 this SO Question 中的 this answer 并扩展了这种想法,使用联合来加入不同方向的查询。

【讨论】:

以上是关于如何生成 sysdate-30 和 sysdate+30 之间的所有日期列表?的主要内容,如果未能解决你的问题,请参考以下文章

定时提醒

sql查询指定月份之前的几个月

单行函数

Oracle获取当前日期前一个月的全部日期

我要在oracle 10g创建一个job,每天凌晨9点执行一个过程,过程名假定为 pro_1001 谢谢指点

《oracle查询语句2》