我有一个SQL表(在SQLite3中),其中我试图聚合来自其他几个表的信息,并且一个表中的记录可能在另一个表中有或没有相应的记录。我的查询应该在聚合表中包含有和没有链接信息的记录。例如:
CREATE TABLE all_households AS
SELECT pop.uid AS pop_uid,
pop.surname,
pop.given,
pop.age,
pop.real_property,
farm.uid AS farm_uid,
farm.improved_acres,
farm.unimproved_acres,
farm.cash_value,
farm.corn,
farm.cotton
FROM pop, farm
WHERE pop.farm_id = farm.uid;
这是查看人口普查时间表的数据。人口普查中的每个人都将拥有基本的pop
信息 - 姓氏,姓名,不动产的价值 - 但不是每个人都有农场。只有某些人在farm_id
上的pop
列中有一个值,对应于farm
上该人的农场记录;否则farm_id
为NULL。
但很自然地,上述查询只会获取那些pop.farm_id = farm.uid
的人 - 也就是说,谁拥有农场,并拥有farm_id
的值。无农场的个人被排除在外,我希望将其包含在farm
中的相关all_households
列的空值中。
现在,我知道我可以解决这个问题,到目前为止,每个链接列都有单独的SELECT语句,如下所示:
CREATE TABLE all_households AS
SELECT uid AS pop_uid,
surname,
given,
age,
real_property,
(SELECT uid FROM farm WHERE pop.farm_id = farm.uid) AS farm_uid,
(SELECT improved_acres FROM farm WHERE pop.farm_id = farm.uid) AS improved_acres,
(SELECT unimproved_acres FROM farm WHERE pop.farm_id = farm.uid) AS unimproved_acres,
(SELECT cash_value FROM farm WHERE pop.farm_id = farm.uid) AS cash_value,
(SELECT corn FROM farm WHERE pop.farm_id = farm.uid) AS corn,
(SELECT cotton FROM farm WHERE pop.farm_id = farm.uid) AS cotton
FROM pop;
但这看起来非常笨重而且不优雅。所以,我想知道是否有办法让上面的第一个查询从pop
中选择条目,其中farm_id
为NULL:
WHERE pop.farm_id = farm.uid OR pop.farm_id IS NULL;
但事情变得非常混乱,我不确定为什么。在我真实的,未简化的查询中,我实际上处理的是四个表,每个表都有pop
上的一列,可能是一个值,也可能是NULL,虽然上面的第一个查询只花了几秒钟,但查询这个WHERE挂了。永远。当我回来时,它已经因“数据库或磁盘已满”的错误而死亡。所以无论我做了什么,我似乎都引发了某种无限循环。我交替尝试了:
WHERE (CASE WHEN pop.farm_id IS NOT NULL THEN pop.farm_id = farm.uid ELSE 1 END);
但这与以前的结果相同。谁能说清楚我做错了什么,或者我可能会做得更好?感谢。
答案 0 :(得分:0)
您尝试使用farm_id IS NULL
的速度很慢,因为数据库试图将每个 farm
记录的组合与每个 {{1记录pop
值。
此外,optimizing constraints with OR is not easy并使用临时表完成。
要获取所有匹配/已加入记录以及第一个表中没有相应服务器场的所有记录,请将两个查询与UNION ALL合并:
NULL
此构造称为outer join,并且在大多数SQL数据库中都是直接支持的(SQLite仅支持左连接,这是您想要的):
SELECT pop. ..., farm. ...
FROM pop JOIN farm ON pop.farm_id = farm.uid
UNION ALL
SELECT pop. ..., NULL, NULL, ...
FROM pop
WHERE pop.farm_id IS NULL
请注意,外部联接实际上会返回所有不匹配的记录,因此这也会返回SELECT pop. ..., farm. ...
FROM pop LEFT OUTER JOIN farm ON pop.farm_id = farm.uid
个记录,其中pop
无效。