Search code examples
sqlleft-joinwith-statementrownum

How to LEFT JOIN on ROW_NUM using WITH


Right now I'm in the testing phase of this query so I'm only testing it on two Queries. I've gotten stuck on the final part where I want to left join everything (this will have to be extended to 12 separate queries). The problem is basically as the title suggests--I want to join 12 queries on the created Row_Num column using the WITH() statement, instead of creating 12 separate tables and saving them as table in a database.

WITH Jan_Table AS
  (SELECT ROW_NUMBER() OVER (ORDER BY a.SALE_DATE) as Row_ID, a.SALE_DATE, sum(a.revenue) as Jan_Rev
  FROM ba.SALE_TABLE a
  WHERE a.SALE_DATE BETWEEN '2015-01-01' and '2015-01-31'
  GROUP BY a.SALE_DATE)

SELECT ROW_NUMBER() OVER (ORDER BY a.SALE_DATE) as Row_ID, a.SALE_DATE, sum(a.revenue) as Jun_Rev, j.Jan_Rev
FROM ba.SALE_TABLE a

LEFT JOIN Jan_Table j
    on "j.Row_ID" = a.Row_ID

WHERE a.SALE_DATE BETWEEN '2015-06-01' and '2015-06-30'
GROUP BY a.SALE_DATE

And then I get this error message:

ERROR: column "j.Row_ID" does not exist

I put in the "j.Row_ID" because the previous message was:

ERROR: column a.row_id does not exist Hint: Perhaps you meant to reference the column "j.row_id".

Each query works individually without the JOIN and WITH functions. I have one for every month of the year and want to join 12 of these together eventually.

The output should be a single column with ROW_NUM and 12 Monthly Revenues columns. Each row should be a day of the month. I know not every month has 31 days. So, for example, Feb only has 28 days, meaning I'd want days 29, 30, and 31 as NULLs. The query above still has the dates--but I will remove the "SALE_DATE" column after I can just get these two queries to join.

My initially thought was just to create 12 tables but I think that'd be a really bad use of space and not the most logical solution to this problem if I were to extend this solution.

edit

Below are the separate outputs of the two qaruies above and the third table is what I'm trying to make. I can't give you the raw data. Everything above has been altered from the actual column names and purposes of the data that I'm using. And I don't know how to create a dataset--that's too above my head in SQL.

Jan_Table (first five lines)

Row_Num        Date          Jan_Rev
1           2015-01-01          20
2           2015-01-02          20
3           2015-01-03          20
4           2015-01-04          20
5           2015-01-05          20

Jun_Table (first five lines)

Row_Num        Date          Jun_Rev
1           2015-06-01          30
2           2015-06-02          30
3           2015-06-03          30
4           2015-06-04          30
5           2015-06-05          30

JOINED_TABLE (first five lines)

Row_Num        Date          Jun_Rev           Date          Jan_Rev
1           2015-06-01          30           2015-01-01          20
2           2015-06-02          30           2015-01-02          20
3           2015-06-03          30           2015-01-03          20
4           2015-06-04          30           2015-01-04          20
5           2015-06-05          30           2015-01-05          20

Solution

  • It seems like you can just use group by and conditional aggregation for your full query:

    select day(sale_date),
           max(case when month(sale_date) = 1 then sale_date end) as jan_date,
           max(case when month(sale_date) = 1 then revenue end) as jan_revenue,
           max(case when month(sale_date) = 2 then sale_date end) as feb_date,
           max(case when month(sale_date) = 2 then revenue end) as feb_revenue,
           . . .
    from sale_table s
    group by day(sale_date)
    order by day(sale_date);
    

    You haven't specified the database you are using. DAY() is a common function to get the day of the month; MONTH() is a common function to get the months of the year. However, those particular functions might be different in your database.