How to generate list of all dates between sysdate-

2020-04-05 09:40发布

Purpose & What I've Got So Far

I am attempting to create a view which checks for missing labor transactions. The view will be fed to a Crystal report.

In this case, the view should take all dates between sysdate+30 and sysdate -30, and then should left outer join all labor records by active employees for each of those dates. It then gives a count of the number of labor transactions for each employee for each date.

This gets passed to the Crystal Report, which will filter based on a specific date range (within the +/- 30 range by the view). From there, the count of all days will summed up per employee in Crystal, and employees will show up which have zero transactions.

The Problem

Without spitting out a list of every date, initially, I'm using labor transaction for each date, but some have no counts for any date. These folks show null transaction dates with zero hours. This indicates they have no charges for the entire period, which makes sense.

However, when Crystal does a filter on that data and selects a range, I believe it leaves out these null values, thus not allowing me to show the full range of folks who don't have time submitted.

The Question

Is there a way to do the equivalent of "select every date between (sysdate+30) and (sysdate-30)" in a view, so that I can use it to compare all the time against?

The SQL (for reference)

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
; 

3条回答
Juvenile、少年°
2楼-- · 2020-04-05 10:26

In order to meet my requirements of being sysdate -30 and sysdate + 30 in a range, this seems be the most elegant way of doing things for now:

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; 

I used this answer from this SO Question and expanded upon that thinking, using a union to join the queries that went in separate directions.

查看更多
Explosion°爆炸
3楼-- · 2020-04-05 10:38
select trunc(sysdate)+31-level from dual connect by level <=61

This is a good method for generating any arbitrary list of values.

查看更多
爷、活的狠高调
4楼-- · 2020-04-05 10:39

Or another method: pick a table with a lot of rows

select sysdate+30 - rownum from user_objects where rownum<61
查看更多
登录 后发表回答