在选择不同的行时统一来自不同表的列
Unify columns from different tables while selecting distinct rows
表格
用户
id
name
email
is_active
1
john
john@albert.com
FALSE
2
mike
mike@ss.com
TRUE
3
monica
monica@dunno.com
TRUE
4
joey
joey@as.com
FALSE
5
ross
ross@boss.com
FALSE
订阅
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
房子
id
name
1
John's House
2
Mike's House
3
Monica's House
4
Joey's House
5
Ross's House
House_Contact(旧版 table)
id
house_id
is_primary
1
1
TRUE
2
2
FALSE
2
3
TRUE
House_User(新table)
id
house_id
is_owner
user_id
1
2
FALSE
2
2
4
FALSE
4
3
5
FALSE
5
预期结果
生成的 table 应包括以下内容:
- 无论状态如何,用户是否都有订阅?如果有,请包括,如果没有,请忽略。
- 从用户 table 获取
email
和 is_active
(如果他们有订阅)
- 获取
is_primary
或 is_owner
(如果他们有订阅)
- 结果应该是不同的(没有重复的用户)
house_id
email
is_owner
is_active
1
john@albert.com
TRUE
FALSE
2
mike@ss.com
FALSE
TRUE
3
monica@dunno.com
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
结果比我删除 INNER JOIN
with UNION
语句的一半。不知道如何进行。
我对统一列和可能的重复感到特别困惑。
您可以按如下方式使用joins
:
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;
如果您在 table 中有多个数据用于匹配条件,我已使用 distinct
删除重复项。不需要的可以去掉。
据我所知,您想从这样的查询开始:
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;
这不是您想要的return,但您的结果是如何得出的还不清楚。
我的有根据的猜测:
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;
我们根本不需要 table house
在查询中。
我看到 三个 可能的冲突来源:
house_contact.is_primary
对比 house_user.is_owner
。两者似乎是同一个意思。数据库设计在这方面被打破了。取两者的 GREATEST()
,这意味着 true
如果其中一个是 true
.
我们不关心 subscription.status
,所以只需确保房子至少有一个订阅任何类型的 EXISTS
,从而避免可能的先验重复。
一个用户可以住多个房子。我们只希望每个用户 one 行。因此,如果有的话,显示第一个 is_primary
的房子(最小 house_id
的那个)。如果没有房子,也没有订阅。但是外面的 LEFT JOIN
让用户留在结果中。更改为 JOIN
以跳过没有订阅的用户。
关于DISTINCT ON
:
- Select first row in each GROUP BY group?
关于对布尔值进行排序:
- Sorting null values after all others, except special
- Sort NULL values to the end of a table
表格
用户
id | name | is_active | |
---|---|---|---|
1 | john | john@albert.com | FALSE |
2 | mike | mike@ss.com | TRUE |
3 | monica | monica@dunno.com | TRUE |
4 | joey | joey@as.com | FALSE |
5 | ross | ross@boss.com | FALSE |
订阅
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 |
房子
id | name |
---|---|
1 | John's House |
2 | Mike's House |
3 | Monica's House |
4 | Joey's House |
5 | Ross's House |
House_Contact(旧版 table)
id | house_id | is_primary |
---|---|---|
1 | 1 | TRUE |
2 | 2 | FALSE |
2 | 3 | TRUE |
House_User(新table)
id | house_id | is_owner | user_id |
---|---|---|---|
1 | 2 | FALSE | 2 |
2 | 4 | FALSE | 4 |
3 | 5 | FALSE | 5 |
预期结果
生成的 table 应包括以下内容:
- 无论状态如何,用户是否都有订阅?如果有,请包括,如果没有,请忽略。
- 从用户 table 获取
email
和is_active
(如果他们有订阅) - 获取
is_primary
或is_owner
(如果他们有订阅) - 结果应该是不同的(没有重复的用户)
house_id | is_owner | is_active | |
---|---|---|---|
1 | john@albert.com | TRUE | FALSE |
2 | mike@ss.com | FALSE | TRUE |
3 | monica@dunno.com | 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
结果比我删除 INNER JOIN
with UNION
语句的一半。不知道如何进行。
我对统一列和可能的重复感到特别困惑。
您可以按如下方式使用joins
:
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;
如果您在 table 中有多个数据用于匹配条件,我已使用 distinct
删除重复项。不需要的可以去掉。
据我所知,您想从这样的查询开始:
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;
这不是您想要的return,但您的结果是如何得出的还不清楚。
我的有根据的猜测:
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;
我们根本不需要 table house
在查询中。
我看到 三个 可能的冲突来源:
house_contact.is_primary
对比house_user.is_owner
。两者似乎是同一个意思。数据库设计在这方面被打破了。取两者的GREATEST()
,这意味着true
如果其中一个是true
.我们不关心
subscription.status
,所以只需确保房子至少有一个订阅任何类型的EXISTS
,从而避免可能的先验重复。一个用户可以住多个房子。我们只希望每个用户 one 行。因此,如果有的话,显示第一个
is_primary
的房子(最小house_id
的那个)。如果没有房子,也没有订阅。但是外面的LEFT JOIN
让用户留在结果中。更改为JOIN
以跳过没有订阅的用户。
关于DISTINCT ON
:
- Select first row in each GROUP BY group?
关于对布尔值进行排序:
- Sorting null values after all others, except special
- Sort NULL values to the end of a table