Reputation: 45
User
id | name | is_active | |
---|---|---|---|
1 | john | [email protected] | FALSE |
2 | mike | [email protected] | TRUE |
3 | monica | [email protected] | TRUE |
4 | joey | [email protected] | FALSE |
5 | ross | [email protected] | FALSE |
Subscriptions
id | house_id | plan name | status |
---|---|---|---|
1 | 1 | A banana a month | inactive |
2 | 2 | An apple a month | active |
3 | 3 | A pear a month | active |
House
id | name |
---|---|
1 | John's House |
2 | Mike's House |
3 | Monica's House |
4 | Joey's House |
5 | Ross's House |
House_Contact (legacy table)
id | house_id | is_primary |
---|---|---|
1 | 1 | TRUE |
2 | 2 | FALSE |
2 | 3 | TRUE |
House_User (new table)
id | house_id | is_owner | user_id |
---|---|---|---|
1 | 2 | FALSE | 2 |
2 | 4 | FALSE | 4 |
3 | 5 | FALSE | 5 |
The resulting table should include the following:
email
& is_active
from User table (if they have subscription)is_primary
OR is_owner
(if they have a subscription)house_id | is_owner | is_active | |
---|---|---|---|
1 | [email protected] | TRUE | FALSE |
2 | [email protected] | FALSE | TRUE |
3 | [email protected] | TRUE | TRUE |
SELECT
u.email AS "email",
u.is_active AS "is_active",
h.id AS "house_id",
is_owner
FROM
house c
INNER JOIN (
SELECT
house_id,
user_id
FROM
house_user) hu ON h.id = hu.house_id
INNER JOIN (
SELECT
id,
email,
is_active
FROM
USER) u ON hu.user_id = u.id
INNER JOIN (
SELECT
id,
email,
is_primary
FROM
house_contact) hc ON u.email = ch.email
INNER JOIN (
SELECT
house_id,
is_primary is_owner
FROM
house_contact
UNION
SELECT
house_id,
is_owner is_owner
FROM
house_user) t ON u.id = t.house_id)
ORDER BY
u.email
Results are half than if I remove the INNER JOIN
with UNION
statement. No idea how to proceed.
I'm particularly confused with unifying the column and the possible duplication.
Upvotes: 0
Views: 101
Reputation: 656291
My educated guess:
SELECT DISTINCT ON (u.id)
u.id, u.email, u.is_active, h.house_id, h.is_primary
FROM "user" u
LEFT JOIN (
SELECT hu.user_id, hu.house_id
, GREATEST(hc.is_primary, hu.is_owner) AS is_primary
FROM house_user hu
LEFT JOIN house_contact hc USING (house_id)
WHERE EXISTS (SELECT FROM subscription WHERE house_id = hu.house_id)
) h ON h.user_id = u.id
ORDER BY u.id, h.is_primary DESC NULLS LAST, h.house_id;
We don't need table house
in the query at all.
I see three possible sources of conflict:
house_contact.is_primary
vs. house_user.is_owner
. Both seem to mean the same. The DB design is broken in this respect. Taking GREATEST()
of both, which means true
if either is true
.
We don't care about subscription.status
, so just make sure the house has at least one subscription of any kind with EXISTS
, thereby avoiding possible duplicates a priori.
A user can live in multiple houses. We want only one row per user. So show the first house with is_primary
(the one with the smallest house_id
) if any. If there is no house, there is also no subscription. But the outer LEFT JOIN
keeps the user in the result. Change to JOIN
to skip users without subscription.
About DISTINCT ON
:
About sorting boolean values:
Upvotes: 1
Reputation: 1269483
From what I can tell, you want to start with a query like this:
select s.house_id, u.email, hu.is_owner, u.is_active
from subscriptions s left join
house_user hu
on s.house_id = hu.house_id left join
users u
on hu.user_id = u.id;
This does not return what you want, but it is rather unclear how your results are derived.
Upvotes: 0
Reputation: 35900
You can use the joins
as follows:
Select distinct hu.house_id, u.email, hu.is_owner, hc.is_primary
From user u join house_user hu on u.id = hu.user_id
Join subscriptions s on s.house_id = hu.house_id
Join house_contract hc on hc.house_id = s.house_id;
I have used distinct
to remove duplicates if you have multiple data in the table for matching condition. You can remove it if not required in case it is not required.
Upvotes: 0