Reputation: 1909
I have table Account
that has zero-to-many Subscription
, and I want to return Account.name
and Subscription.end
.
If there's no active subscription, Subscription.end
should be NULL
.
This is my (incorrect) SQL:
SELECT acc.name,
s.t_end
FROM ACCOUNT acc LEFT JOIN SUBSCRIPTION s ON acc.id = s.account_id
WHERE acc.id = 1
AND s.t_start <= CURRENT_TIMESTAMP()
AND s.t_end > CURRENT_TIMESTAMP()
The problem with my SQL: If there's no matching subscription for the account, it will return empty set:
acc.name | s.t_end
------------------
<nothing>
What I want:
acc.name | s.t_end
------------------
1 | NULL
Upvotes: 2
Views: 59
Reputation: 28834
Whenever using Left Join
, if there are any Where
conditions on the right-side tables; it will limit the data, and you will not get all the rows from the left-most table as desired.
Instead, you can shift the Where
conditions on the right-side tables to the join ON
condition:
SELECT acc.name,
s.t_end
FROM ACCOUNT acc
LEFT JOIN SUBSCRIPTION s ON acc.id = s.account_id AND
s.t_start <= CURRENT_TIMESTAMP() AND
s.t_end > CURRENT_TIMESTAMP()
WHERE acc.id = 1
Also, it is generally a good practice to put as many conditions as possible into the JOIN ON
conditions, as it increases readability of the queries. It will be much easier to change these queries as well, in case the Join type is being changed.
Upvotes: 4
Reputation: 13
you are applying where condition on subscription table , so the because of the where condition the left join behaves like an inner join.
Try eliminating the where condition, if you can't you can use below query-
SELECT acc.name,
s.t_end
FROM ACCOUNT acc
LEFT JOIN
(select account_id,t_end from SUBSCRIPTION
where
t_start <= CURRENT_TIMESTAMP()
and t_end > CURRENT_TIMESTAMP()
) s
ON acc.id = s.account_id
WHERE acc.id = 1
Upvotes: 0