我编写了一个相对高性能的PostgresSQL查询,并为我提供了我想要的数据集,但我想知道它是否是编写查询的最简单/最好的方法。似乎应该有一个更简单的连接操作来满足我需要的条件。
编辑:我确实需要这个才能在大型表格上表现出色。在下面给出的例子中,宠物是1.5亿行,食物大约是100k行。我的解决方案在底部时钟约为0.6毫秒。两个表都有id和user_id的索引。食物表还包括pet_id的索引。
我的系统中有两个与一个保证共享属性相关的表 - user_id。这是一个实质上显示我的问题的例子:
宠物
+------+-------+---------+
| id | type | user_id |
+------+-------+---------+
| 1234 | dog | 1 |
| 1235 | cat | 1 |
| 1236 | gecko | 1 |
+------+-------+---------+
食品
+------+-----------+---------+--------+
| id | name | user_id | pet_id |
+------+-----------+---------+--------+
| 4321 | hamburger | 1 | NULL |
| 4322 | dog food | 1 | 1234 |
| 4323 | cat food | 1 | 1235 |
+------+-----------+---------+--------+
期望的结果
+------+------+
| p.id | f.id |
+------+------+
| NULL | 4321 | --no pet, hamburger
| 1234 | 4322 | --dog, dog food
| 1235 | 4323 | --cat, cat food
| 1236 | NULL | --gecko, no food
+------+------+
现在有一个例子可以参考,我会确定结果是什么。结果包含属于我的user_id的两侧的所有行(假设该表可能包含数千个不属于user_id 1的其他行)。我希望这些结果行包含与另一个表匹配的每一行的一个副本。
我尝试使其完成外部联接的示例:
SELECT p.id, f.id
FROM pets p FULL OUTER JOIN food f ON p.user_id = f.user_id
WHERE p.user_id = 1;
此查询中存在一些问题,因为
NULL
个。我需要那些。我可以通过在OR
过滤器中添加WHERE
来修复#1:
SELECT p.id, f.id
FROM pets p FULL OUTER JOIN food f ON p.user_id = f.user_id
WHERE p.user_id = 1 OR f.user_id = 1;
由于我不完全确定的原因,它会使查询花费很长时间。在我们的系统中,两个表都有一个user_id索引,因此不缺少索引。
为了解决我的问题,我登陆了以下查询(实际上是两个组合):
SELECT p.id, f.id
FROM pets p LEFT JOIN food f
ON p.id = f.pet_id AND f.user_id = 1
WHERE p.user_id = 1
UNION
SELECT p.id, f.id FROM pets p RIGHT JOIN food f
ON p.id = f.pet_id
WHERE f.user_id = 1 AND p.id IS NULL;
所以我的问题是:有一种更简单的方法可以将其作为单个查询执行吗?
答案 0 :(得分:3)
<强> SQL DEMO 强>
SELECT p.id, f.id
FROM pets p
FULL OUTER JOIN food f
ON p.user_id = f.user_id
AND p.id = f.pet_id
AND p.user_id = 1;
输出
| id | id |
|--------|--------|
| 1234 | 4322 |
| 1235 | 4323 |
| 1236 | (null) |
| (null) | 4321 |
注意:强>
您应该在(user_id, pet_id)
上为两个表添加复合索引。
答案 1 :(得分:2)
你只是过度思考这一点。您想加入P.ID = F.PET_ID
:
SELECT P.ID, F.ID
FROM PETS P
FULL OUTER JOIN FOOD F ON P.ID = F.PET_ID
AND P.USER_ID = F.USER_ID
AND P.USER_ID = 1 --optional
ORDER BY P.ID