'Join on two columns, if null then only join on one
I have the following two tables:
customers:
| customer_id | department_id |
|---|---|
| aaaa | 1234 |
| bbbb | 3456 |
status:
| department_id | customer_id | status |
|---|---|---|
| 1234 | NULL | silver |
| 3456 | bbbb | gold |
| 1234 | bbbb | gold |
I want to join status on customers, but if if it returns NULL I want to give the customer the department default. My ideal Output for this would be the following:
| customer_id | department_id | status |
|---|---|---|
| aaaa | 1234 | silver |
| bbbb | 3456 | gold |
I have tried to do two left joins, but am getting a memory usage error. Is there another way to do this that is efficient?
Solution 1:[1]
You can do:
select c.*, coalesce(s.status, d.status) as status
from customers c
left join status d on d.department_id = c.department_id
and d.customer_id is null
left join status s on s.department_id = c.department_id
and s.customer_id = c.customer_id
Solution 2:[2]
This might work:
SELECT *,
(
SELECT TOP 1 status
FROM status s
WHERE s.customer_id = c.customer_id
OR (c.customer_id IS NULL AND s.department_id = c.department_id)
ORDER BY CASE WHEN s.customer_id is NOT NULL THEN 0 ELSE 1 END
) as status
FROM customers c
The kicker is what kind of database you're using. If it's MySql you might want LIMIT 1 instead of TOP 1. For Oracle you'd look at the ROWNUM field.
Solution 3:[3]
Assuming that there is always a match at least on the department_id, you need an INNER join and FIRST_VALUE() window function will pick the proper status:
SELECT DISTINCT
c.customer_id,
c.department_id,
FIRST_VALUE(s.status) OVER (
PARTITION BY c.customer_id, c.department_id
ORDER BY CASE
WHEN s.customer_id = c.customer_id THEN 1
WHEN s.customer_id IS NULL THEN 2
ELSE 3
END
) status
FROM customers c INNER JOIN status s
ON s.department_id = c.department_id;
Depending on the database that you use the code may be simplified.
See the demo.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | The Impaler |
| Solution 2 | Joel Coehoorn |
| Solution 3 | forpas |
