I have two tables:
a
| WEEK_DATE | DAY_NUMBER |
|---|---|
| 8/17/2022 | 1 |
| 8/18/2022 | 2 |
| 8/19/2022 | 3 |
| 8/22/2022 | 4 |
| 8/23/2022 | 5 |
| 8/24/2022 | 6 |
| 8/25/2022 | 7 |
| 8/26/2022 | 8 |
| 8/29/2022 | 9 |
b
| START_DATE | END_DATE | PERSON |
|---|---|---|
| 8/17/2022 | 8/18/2022 | Jack |
| 8/23/2022 | 8/29/2022 | Jack |
I am trying to determine the week days that Jack missed, which would look like this:
| PERSON | WEEK_DATE | DAY_NUMBER |
|---|---|---|
| Jack | 8/19/2022 | 3 |
| Jack | 8/22/2022 | 4 |
Right now, this is my query and the results below:
SELECT
b.START_DATE,
b.END_DATE,
b.PERSON,
a.WEEK_DATE,
a.DAY_NUMBER
FROM b
LEFT JOIN a
ON a.WEEK_DATE BETWEEN b.START_DATE AND b.END_DATE
| START_DATE | END_DATE | PERSON | WEEK_DATE | DAY_NUMBER |
|---|---|---|---|---|
| 8/17/2022 | 8/18/2022 | Jack | 8/17/2022 | 1 |
| 8/17/2022 | 8/18/2022 | Jack | 8/18/2022 | 2 |
| 8/23/2022 | 8/29/2022 | Jack | 8/23/2022 | 5 |
| 8/23/2022 | 8/29/2022 | Jack | 8/24/2022 | 6 |
| 8/23/2022 | 8/29/2022 | Jack | 8/25/2022 | 7 |
| 8/23/2022 | 8/29/2022 | Jack | 8/26/2022 | 8 |
| 8/23/2022 | 8/29/2022 | Jack | 8/29/2022 | 9 |
How do I get the JOIN to include Jack’s missed days as shown previously (days 3 and 4)? Even as nulls like this:
| START_DATE | END_DATE | PERSON | WEEK_DATE | DAY_NUMBER |
|---|---|---|---|---|
| 8/17/2022 | 8/18/2022 | Jack | 8/17/2022 | 1 |
| 8/17/2022 | 8/18/2022 | Jack | 8/18/2022 | 2 |
| (null) | (null) | Jack | 8/19/2022 | (null) |
| (null) | (null) | Jack | 8/22/2022 | (null) |
| 8/23/2022 | 8/29/2022 | Jack | 8/23/2022 | 5 |
| 8/23/2022 | 8/29/2022 | Jack | 8/24/2022 | 6 |
| 8/23/2022 | 8/29/2022 | Jack | 8/25/2022 | 7 |
| 8/23/2022 | 8/29/2022 | Jack | 8/26/2022 | 8 |
| 8/23/2022 | 8/29/2022 | Jack | 8/29/2022 | 9 |
>Solution :
You have two options, either use a RIGHT JOIN:
SELECT
b.START_DATE,
b.END_DATE,
b.PERSON,
a.WEEK_DATE,
a.DAY_NUMBER
FROM b
RIGHT JOIN a
ON a.WEEK_DATE BETWEEN b.START_DATE AND b.END_DATE
--WHERE a.DAY_NUMBER IS NULL
Or, swap your table order:
SELECT
b.START_DATE,
b.END_DATE,
b.PERSON,
a.WEEK_DATE,
a.DAY_NUMBER
FROM a
LEFT JOIN b
ON a.WEEK_DATE BETWEEN b.START_DATE AND b.END_DATE
--WHERE a.DAY_NUMBER IS NULL
I would recommend the second option as pretty much everyone writes SQL to use LEFT JOINs, so they are the more easily understood option.
EDIT to add some further explanation:
The only time you’ll ever want a LEFT JOIN or RIGHT JOIN are in cases like these where you need to conserve rows that would be filtered out by an INNER JOIN.
If you a look at a basic from/join:
FROM table a
JOIN table b
The top table a is the left table, the bottom table b is the right table. Same is generally true for later joins:
JOIN table a ...
JOIN table b on a.id = b.id
Table a is left, table b is right.
So if you want to conserve rows from table a, you would want a LEFT JOIN:
FROM table a
LEFT JOIN table b
If you wanted to conserve rows from table b, then we loop back to your original situation, and you could RIGHT JOIN:
FROM table a
RIGHT JOIN table b
But again, everyone always uses LEFT JOINs as the standard, so you’d be better off swapping the table order and using a left:
FROM table b
LEFT JOIN table a