PostgreSQL 查询:左外部连接 "where",但如果不存在则为空值
PostgreSQL query: left outer join with "where" but also null values if not existing
我在无法修改的 PostgreSQL 数据库中有两个 table(我只是想从中获取信息的 COTS 软件)。
一个有用户信息:
| id | username | mail |
+----+----------+---------------+
| 1 | admin | admin@xzy.com |
| 2 | user | user@xzy.com |
...和一个额外的 table 具有用户属性:
| user_id | attribute_name | attribute_value |
+---------+-----------------+-------------------+
| 1 | active | true |
| 1 | loginDateMillis | 1652176627 |
| 2 | active | true |
我需要的是所有用户及其 loginDateMillis(如果存在),否则为“null”或空,例如:
| id | username | mail | attribute_value |
+----+----------+---------------+-----------------+
| 1 | admin | admin@xzy.com | 1652176627 |
| 2 | user | user@xzy.com | null |
起初我尝试将两个 table 与 where 条件连接到 select 只有 attribute_name = 'loginDateMillis'
,但后来我过滤掉空行:
> select u.id, u.username, u.mail, a.attribute_value
from users u
left outer join user_attributes a
on a.user_id = u.id
where a.attribute_name = 'loginDateMillis';
| id | username | mail | attribute_value |
+----+----------+---------------+-----------------+
| 1 | admin | admin@xzy.com | 1652176627 |
我能找到的唯一解决方案是为每个用户获取一行,还有属性,是按用户列分组并使用 array_agg 函数:
> select u.id, u.username, u.mail, array_agg(a.attribute_name), array_agg(a.attribute_value)
from users u
left outer join user_attributes a
on a.user_id = u.id
group by (u.id, u.username, u.mail);
| id | username | mail | attribute_name | attribute_value |
+----+----------+---------------+---------------------------+--------------------+
| 1 | admin | admin@xzy.com | {active, loginDateMillis} | {true, 1652176627} |
| 2 | user | user@xzy.com | {active} | {true} |
这“还可以”,因为我可以在我的应用程序中过滤数组,但也许我在这里遗漏了一些明显的东西?非常感谢。
如果将 WHERE
子句中的逻辑移动到 ON
子句中,它应该会按预期工作:
select u.id, u.username, u.mail, a.attribute_value
from users u
left join user_attributes a
on a.user_id = u.id and a.attribute_name = 'loginDateMillis';
我在无法修改的 PostgreSQL 数据库中有两个 table(我只是想从中获取信息的 COTS 软件)。
一个有用户信息:
| id | username | mail |
+----+----------+---------------+
| 1 | admin | admin@xzy.com |
| 2 | user | user@xzy.com |
...和一个额外的 table 具有用户属性:
| user_id | attribute_name | attribute_value |
+---------+-----------------+-------------------+
| 1 | active | true |
| 1 | loginDateMillis | 1652176627 |
| 2 | active | true |
我需要的是所有用户及其 loginDateMillis(如果存在),否则为“null”或空,例如:
| id | username | mail | attribute_value |
+----+----------+---------------+-----------------+
| 1 | admin | admin@xzy.com | 1652176627 |
| 2 | user | user@xzy.com | null |
起初我尝试将两个 table 与 where 条件连接到 select 只有 attribute_name = 'loginDateMillis'
,但后来我过滤掉空行:
> select u.id, u.username, u.mail, a.attribute_value
from users u
left outer join user_attributes a
on a.user_id = u.id
where a.attribute_name = 'loginDateMillis';
| id | username | mail | attribute_value |
+----+----------+---------------+-----------------+
| 1 | admin | admin@xzy.com | 1652176627 |
我能找到的唯一解决方案是为每个用户获取一行,还有属性,是按用户列分组并使用 array_agg 函数:
> select u.id, u.username, u.mail, array_agg(a.attribute_name), array_agg(a.attribute_value)
from users u
left outer join user_attributes a
on a.user_id = u.id
group by (u.id, u.username, u.mail);
| id | username | mail | attribute_name | attribute_value |
+----+----------+---------------+---------------------------+--------------------+
| 1 | admin | admin@xzy.com | {active, loginDateMillis} | {true, 1652176627} |
| 2 | user | user@xzy.com | {active} | {true} |
这“还可以”,因为我可以在我的应用程序中过滤数组,但也许我在这里遗漏了一些明显的东西?非常感谢。
如果将 WHERE
子句中的逻辑移动到 ON
子句中,它应该会按预期工作:
select u.id, u.username, u.mail, a.attribute_value
from users u
left join user_attributes a
on a.user_id = u.id and a.attribute_name = 'loginDateMillis';