postgresql - 如何进行有条件联接?
问题描述
我有以下查询
SELECT p.first_name || ' ' || p.last_name as full_name, p.user_id,
u.email, u.username,
(
SELECT EXTRACT (year from (age(now(), p.date_of_birth)))
)age,
co.name as country, s.name as state, c.name as city,
(
SELECT country.phonecode FROM countries country WHERE ph.country_id = country.id
)phone_code, ph.area_code, ph.number as phone_number,
(
SELECT i.path FROM images i WHERE i.id = p.image_id
)avatar
FROM people p
JOIN users u ON u.id = p.user_id
JOIN addresses a ON a.id = p.address_id
JOIN cities c ON c.id = a.city_id
JOIN states s ON s.id = c.state_id
JOIN countries co ON co.id = s.country_id
JOIN phones ph ON ph.person_id = p.id
WHERE (
SELECT u.status FROM users u WHERE u.id = p.user_id
) = 'U'
ORDER BY p.id DESC
但是,有些人不一定有信息,Address
而Phone
我无论如何都想带上这些信息,我该怎么做?
小例子:
用户
+----+-----------+-----------+---------------+-------------------------+
| id | username | role | status | email |
+----+-----------+-----------+---------------+-------------------------+
| 7 | Shibari | P | U | deathwrap@live.ca |
| 12 | Josh23 | P | U | heeman@gmail.ca |
| 13 | Test22 | P | U | test@gmail.ca |
+----+-----------+-----------+---------------+-------------------------+
人们
+----+----------+-----------+-------------+-------+------------+----------+
| id |first_name| last_name |date_of_birth|user_id| address_id | image_id |
+----+----------+-----------+-------------+-------+------------+----------+
| 7 | Edward | Test | 1983-10-13 | 7 | 11 | [null] |
| 12 | Josh | Test | 1996-04-11 | 12 | [null] | 7 |
| 13 | Gavin | Cringe | 1991-04-11 | 13 | 18 | 8 |
+----+----------+-----------+-------------+-------+-----------------------+
地址
+----+---------------------+-----------+---------------+
| id | name | zip_code | city_id |
+----+---------------------+-----------+---------------+
| 11 | Rue De La Fonderie |[null] | 26497 |
| 18 | Av. Test |[null] | 6486 |
+----+---------------------+-----------+---------------+
城市
+-----+---------------------+-----------+
| id | name | state_id |
+-----+---------------------+-----------+
|6486 | Resistencia |210 |
|26497| Luxembourg |2237 |
+-----+---------------------+-----------+
状态
+-----+---------------------+-----------+
| id | name |country_id |
+-----+---------------------+-----------+
|210 | Chaco |10 |
|2237 | Luxembourg |127 |
+-----+---------------------+-----------+
国家
+-----+---------------------+-----------+
| id | name | phonecode |
+-----+---------------------+-----------+
|10 | Argentina |54 |
|127 | Luxembourg |352 |
+-----+---------------------+-----------+
电话
+----+-----------+-----------+---------------+-------------+
| id | area_code | number | person_id | country_id |
+----+-----------+-----------+---------------+-------------+
| 6 | 661 | 12345 | 7 | 127 |
+----+-----------+-----------+---------------+-------------+
图片
+-----+----------------+
| id | path |
+-----+----------------+
|7 | 7.jpg |
|8 | 8.jpg |
+-----+----------------+
这是我想要的输出
+------------+-------+-----------------+--------+---+----------+----------+-----------+----------+
| full_name |user_id| email |username|age|country |state |city |phone_code|
+------------+-------+-----------------+--------+---+----------+----------+-----------+----------+
|Edward Test |7 |deathwrap@live.ca|Shibari |37 |Luxembourg|Luxembourg|Luxembourg |352 |
|Josh Test |12 |heeman@gmail.ca |Josh23 |24 |[null] |[null] |[null] |[null] |
|Gavin Cringe|13 |test@gmail.ca |Test22 |29 |Argentina |Chaco |Resistencia|[null] |
+------------+-------+-----------------+--------+---+----------+----------+-----------+----------+
+------------+------------+-----------------+
| area_code |phone_number| avatar |
+------------+------------+-----------------+
|661 |12345 | [null] |
|[null] |[null] | 7.jpg |
|[null] |[null] | 8.jpg |
+------------+------------+-----------------+
目前它只是打印第一个条目,因为它同时链接了地址和电话号码,但是即使没有链接电话号码或地址,我也想打印此信息,我该怎么做?
解决方案
使用左连接而不是内连接:
SELECT ...
FROM people p
LEFT JOIN users u ON u.id = p.user_id AND u.status = 'U'
LEFT JOIN addresses a ON a.id = p.address_id
LEFT JOIN cities c ON c.id = a.city_id
LEFT JOIN states s ON s.id = c.state_id
LEFT JOIN countries co ON co.id = s.country_id
LEFT JOIN phones ph ON ph.person_id = p.id
使用上面的左连接方法应该确保每个人员记录都出现在输出中,即使它与一个或多个 otber 表不匹配。请注意,我已将检查status
从WHERE
子句移至ON
与表的左连接子句users
。
推荐阅读
- sql - 如何在 SQL 条件语句中使用查询参数
- python-3.x - Pandas 合并在大型数据帧上很慢
- javascript - 以 Modal 输出 MySQL 数据
- vue.js - 打开页面时预渲染页面闪烁中具有 v-show="false" 属性的元素
- mongodb - MongoDB/Mongoose 使用聚合获取对象数组属性的长度
- android - 我想我在 android 文档上发现了一个错字
- ios - 如何让 imageView 占用 CollectionView 单元格?
- pytorch - Pytorch.Embedding 中的 from_pretrained 和 weight.data.copy 有什么区别
- android - React native sound is too slow when loading a sound from url (delay)
- regex - Add additional field in fluentd