Reputation: 31
I have an issue where my SQL query will not get rid of null values.
I have tried a myriad of different techniques, but I am a novice.
My desired result is an Order number followed by the date which the status occurs all in one line.
select mo.order_id OrderID,
case when osr.order_status_cd = 120 and osr.create_date is not null then osr.create_date end as POCreated,
case when osr.order_status_cd = 220 and osr.create_date is not null then osr.create_date end as Ordered,
case when osr.order_status_cd = 300 and osr.create_date is not null then osr.create_date end as Shipped,
case when osr.order_status_cd = 400 and osr.create_date is not null then osr.create_date end as Received,
case when osr.order_status_cd = 500 and osr.create_date is not null then osr.create_date end as Completed,
from order_status_record osr
inner join msorder mo on mo.order_id = osr.msorder_id
Instead of getting results that look like this:
OrderID POCreated Ordered Shipped Received Completed
497822 11/18/2012 NULL NULL NULL NULL
497822 NULL 11/19/2012 NULL NULL NULL
497822 NULL NULL 11/19/2012 NULL NULL
497822 NULL NULL NULL 11/19/2012 NULL
497822 NULL NULL NULL NULL 11/19/2012
I want this:
OrderID POCreated Ordered Shipped Received Completed
497822 11/18/2012 11/19/2012 11/19/2012 11/19/2012 11/19/2012
Do I need to create a virtual table? Do I need an if function? Why do the Nulls still populate?
Any help would be much appreciated.
Thanks,
Andrew
Upvotes: 2
Views: 169
Reputation: 115520
Assuming that (msorder_id, order_status_cd)
is UNIQUE
in table order_status_record
, here is a solution without GROUP BY
:
SELECT
mo.order_id AS OrderID,
osr120.create_date AS POCreated,
osr220.create_date AS Ordered,
osr300.create_date AS Shipped,
osr400.create_date AS Received,
osr500.create_date AS Completed
FROM
msorder AS mo
LEFT JOIN
order_status_record AS osr120
ON osr120.msorder_id = mo.order_id
AND osr120.order_status_cd = 120
LEFT JOIN
order_status_record AS osr220
ON osr220.msorder_id = mo.order_id
AND osr220.order_status_cd = 220
LEFT JOIN
order_status_record AS osr300
ON osr300.msorder_id = mo.order_id
AND osr300.order_status_cd = 300
LEFT JOIN
order_status_record AS osr400
ON osr400.msorder_id = mo.order_id
AND osr400.order_status_cd = 400
LEFT JOIN
order_status_record AS osr500
ON osr500.msorder_id = mo.order_id
AND osr500.order_status_cd = 500 ;
Upvotes: 2
Reputation: 102743
Use GROUP BY
to group the order IDs into a row, and MAX
on the case statements to get the right row:
select mo.order_id OrderID,
MAX(case when osr.order_status_cd = 120 and osr.create_date is not null then osr.create_date end) as POCreated,
MAX(case when osr.order_status_cd = 220 and osr.create_date is not null then osr.create_date end) as Ordered,
MAX(case when osr.order_status_cd = 300 and osr.create_date is not null then osr.create_date end) as Shipped,
MAX(case when osr.order_status_cd = 400 and osr.create_date is not null then osr.create_date end) as Received,
MAX(case when osr.order_status_cd = 500 and osr.create_date is not null then osr.create_date end) as Completed,
from order_status_record osr
inner join msorder mo on mo.order_id = osr.msorder_id
GROUP BY order_id
Upvotes: 2
Reputation: 247650
If you add an aggregate function to each of the CASE
statements and then a GROUP BY
the records will consolidate into a single row:
select mo.order_id OrderID,
max(case when osr.order_status_cd = 120 and osr.create_date is not null then osr.create_date end) as POCreated,
max(case when osr.order_status_cd = 220 and osr.create_date is not null then osr.create_date end) as Ordered,
max(case when osr.order_status_cd = 300 and osr.create_date is not null then osr.create_date end) as Shipped,
max(case when osr.order_status_cd = 400 and osr.create_date is not null then osr.create_date end) as Received,
max(case when osr.order_status_cd = 500 and osr.create_date is not null then osr.create_date end) as Completed,
from order_status_record osr
inner join msorder mo
on mo.order_id = osr.msorder_id
group by mo.order_id
Upvotes: 3