0

I am building a chart and need to have all of the days of a given month represented for applications submitted. On some days, there may be 5 and on others there may be 0. I am getting my data from an applications table but I need append the string for dates that do not have a value. For example today is 05/29 and 3 people applied. On 05/21, 2 people applied. In between (and before that) no others applied. So I need to get those dates and store a 0 value for them.

Below is what I am using to bring back and group the data:

SELECT DISTINCT to_char ("applicationdate",'mm') AS applicationmonth
      , to_char ("applicationdate",'dd') AS applicationdate
      , to_char ("applicationdate", 'yyyy') AS applicationyear
      , term
      , COUNT(*) AS count
FROM  campapplications.basketball
WHERE term = 'SU' 
GROUP BY applicationdate, term
ORDER BY applicationdate, term

At the end of the day, I am doing an insert.

I have looked other places but could not really get any input outside of using the listAppend() function.

SOS
  • 6,430
  • 2
  • 11
  • 29
  • (Edit) Which DBMS, oracle? Are *all* of those columns in the chart, or only some? Please post the relevant charting code? – SOS May 29 '19 at 22:26

1 Answers1

3

It's not clear how "appending a string" relates to charting or inserts... However, just focusing on the query, either a calendar table or CTE could be used generate all dates within a specific date range. (For larger data sets, a calendar table is usually better). Once you have the dates, outer join them back to your application table to get the counts for each date.

You didn't mention which DBMS you are using, but from the syntax I'm guessing Oracle. Assuming the "applicationDate" column ONLY contains a date (no time), the query below would return a count for all dates within the given range: #startDate# and #endDate#. Adjust the dates as needed.

SQL: http://sqlfiddle.com/#!4/c09877/2

WITH CTE(TheDate) AS
(
    SELECT FromDate+level-1
    FROM (
        SELECT <cfqueryparam value="#startDate#" cfsqltype="cf_sql_date"> AS FromDate
               , <cfqueryparam value="#endDate#" cfsqltype="cf_sql_date">  AS ToDate 
        FROM   dual
     ) d
     CONNECT BY LEVEL <=  ToDate - FromDate + 1
)
SELECT TheDate
      , COUNT(b.applicationDate) AS count
FROM   cte LEFT JOIN basketball b ON b.applicationDate = cte.TheDate
GROUP BY TheDate
ORDER BY TheDate      
;

Sample Results:

|              THEDATE | COUNT |
|----------------------|-------|
| 2019-05-21T00:00:00Z |     2 |
| 2019-05-22T00:00:00Z |     0 |
| 2019-05-23T00:00:00Z |     0 |
| 2019-05-24T00:00:00Z |     0 |
| 2019-05-25T00:00:00Z |     0 |
| 2019-05-26T00:00:00Z |     0 |
| 2019-05-27T00:00:00Z |     0 |
| 2019-05-28T00:00:00Z |     0 |
| 2019-05-29T00:00:00Z |     3 |

Update:

I'm not great with PostgreSQL, but this thread shows how to generate a date range. Just replace the hard coded dates with cfqueryparam.

SQL: http://sqlfiddle.com/#!15/2a0a7/4

SELECT TheDate
      , COUNT(b.applicationDate) AS count
FROM  generate_series
        ( '2019-05-21'::date 
        , '2019-05-29'::date
        , '1 day'::interval) TheDate 
       LEFT JOIN basketball b ON b.applicationDate = TheDate
GROUP BY TheDate
ORDER BY TheDate
SOS
  • 6,430
  • 2
  • 11
  • 29
  • Many thanks for the assistance. We are using Postgres for the DBMS. – John Eubanks May 30 '19 at 14:48
  • Okay. Added that to the question tags for SEO. I don't use Postgres, but see the updated answer for one possibility. Note, I had to omit the schema to create a working fiddle. – SOS May 30 '19 at 15:01
  • Ageax, it works like a charm...many, many, thanks...I was hoping to NOT have to do a lot of conditional checking within a list. Have a great one. – John Eubanks May 30 '19 at 16:13
  • Glad it helped! – SOS May 30 '19 at 16:20
  • 1
    I am of the firm opinion that just about every database should have some sort of calendar table and a numbers table. They are very easy to create. They use very low resources. And they are IMMENSELY useful, especially in situations like this. – Shawn May 30 '19 at 16:46
  • 1
    @Shawn - I wasn't a fan at first. I.e. "Why do I need to create a permanent table? Seems so cumbersome! Etc..." .. but you do enough repoting queries, you eventually you hit the limits of cte's and learn to embrace the benefits of calendar tables ;-) – SOS May 30 '19 at 20:20
  • 1
    @Ageax Not just the limits of CTEs, but if you work with a large enough data set, a set-based helper table JOIN will usually far outperform most other options for very little cost. And what cost there is was already paid for one time at creation of the helper table. Personally, I'd be happy if dbms creators started including them by default. – Shawn May 30 '19 at 20:28
  • 1
    @Shawn - Yep, that's one of the "limits" I was alluding to. The penalties start to outweigh the gains as the data sets get larger. *if dbms creators started including them by default* Now that would be awesome. Make it UTC time and it would be perfect.... – SOS May 30 '19 at 20:43
  • _Make it UTC time and it would be perfect._ Then that would take away all the fun of trying to figure out when your user in Kathmandu logged in. :-/ – Shawn May 30 '19 at 20:56
  • I am okay with that. I have had my fill of "fun" ;-) – SOS May 30 '19 at 22:01