假设我在PostgreSQL中有三个表:
table1 - id1, a_id, updated_by_id
table2 - id2, a_id, updated_by_id
Users - id, display_name
假设我使用以下查询:
select count(t1.id1) from table1 t1
left join table2 t2 on (t1.a_id=t2.a_id)
full outer join users u1 t1.updated_by_id=u1.id)
full outer join users u2 t2.updated_by_id=u2.id)
where u1.id=100;
我将50
作为计数。
然而:
select count(t1.id1) from table1 t1
left join table2 t2 on (t1.a_id=t2.a_id)
full outer join users u1 t1.updated_by_id=u1.id)
full outer join users u2 t2.updated_by_id=u2.id)
where u2.id=100;
我只获得25
作为计数。
第二个查询中我的错误是什么?我能做些什么来获得相同的数量?
我的要求是有一个用户表,由多个表引用。我想获取完整的用户列表,并从不同的表中获取ID的数量。
但我单独参加的桌子会返回正确的计数,但其余的人不会返回正确的计数。任何人都可以建议一种方法来修改我的第二个查询以获得正确的计数吗?
答案 0 :(得分:2)
要简化逻辑,请先聚合,稍后再加入。
猜测错过的详细信息,此查询会为您提供准确的计数,table1
和table2
分别为所有用户分别引用每个用户的次数:
SELECT *
FROM users u
LEFT JOIN (
SELECT updated_by_id AS id, count(*) AS t1_ct
FROM table1
GROUP BY 1
) t1 USING (id)
LEFT JOIN (
SELECT updated_by_id AS id, count(*) AS t2_ct
FROM table2
GROUP BY 1
) t2 USING (id);
特别是,当连接在一起时,避免多个1-n关系相互重叠:
要仅检索单个或少数用户,LATERAL
加入速度会更快(Postgres 9.3 +):
SELECT *
FROM users u
LEFT JOIN LATERAL (
SELECT count(*) AS t1_ct
FROM table1
WHERE updated_by_id = u.id
) ON true
LEFT JOIN LATERAL (
SELECT count(*) AS t2_ct
FROM table2
WHERE updated_by_id = u.id
) ON true
WHERE u.id = 100;
您报告的特定不匹配是由于FULL OUTER JOIN
:
首先,执行内连接。然后,对于T1中的每一行 不满足T2中任何行的连接条件,连接的行是 在T2列中添加了空值。另外,对于T2的每一行 不满足T1中任何行(连接行)的连接条件 添加了T1列中的空值。
因此,对于缺少的匹配,您将在相应的另一侧附加NULL值。 count()
不计算NULL值。因此,您可以根据是否对u1.id=100
或u2.id=100
进行过滤来获得不同的结果。
这只是为了解释,你这里不需要FULL JOIN
。请改用现有的替代方案。