LEFT OUTER JOIN 不能在没有连接两边的字段相等的条件下使用

Posted

技术标签:

【中文标题】LEFT OUTER JOIN 不能在没有连接两边的字段相等的条件下使用【英文标题】:LEFT OUTER JOIN cannot be used without a condition that is an equality of fields from both sides of the join 【发布时间】:2019-11-17 15:20:17 【问题描述】:

我的表 categories 具有以下结构:

我正在尝试在parentId = id 上进行自联接以获取父类别,但我还希望查询包含没有联接的行。 我试着做:

select *
from `project.dataset.categories` c
left join `project.dataset.categories` p1 on p1.id = c.parentId or p1.id = c.id

但这会引发

由于我无法理解的原因。

所以基本上我期待这样的结果:

遗憾的是,使用 union 不是一种选择,因为这只是对更复杂的查询的简化。

任何帮助。

【问题讨论】:

您需要更好地解释您想要什么。 UNION ALL 清楚地解决了您所说的问题。您应该使用该解决方案。 @GordonLinoff 是的,我知道,但实际上我这样做了 15 次,最终也需要每个“原始”行,所以联合不起作用,因为我需要解决前一个问题数据集最终会产生很多我想避免的重复代码。 您可以使用 CTE,因此代码只需要编写一次。 @GordonLinoff 是的,我考虑过,但我读到使用 CTE 确实会运行两次查询,因为原始查询更复杂,所以查询时间会更长。 我相信 BigQuery 会在左连接上强制执行明确的相等条件,以防止意外扇出(如果您正在写入表,这可能会产生延迟存储成本)。您的查询具有条件连接逻辑 (or),这似乎是这里的问题。此处未列出的另一个解决方案是执行 2 个自连接(1 个在 parentID 上,1 个在 id 上),然后使用 coalescecase 语句来选择您想要的字段。 【参考方案1】:

我认为你可以做到:

select cc.*
from `project.dataset.categories` c cross join
     unnest(array[id, parent_id]) c_id left join
     categories cc
     on cc.id = c_id
-- where c.id = 2106  -- you seem to want this condition as well

这将创建一个包含您要连接的两列的数组 -- 然后将它们取消嵌套到 join 的两个单独的行中。

或者只使用orexists

select c.*
from `project.dataset.categories` c
where c.id = 2106 or
      exists (select 1
              from `project.dataset.categories` c2
              where c2.id = 2016 and c2.parentid = c.id
             );

【讨论】:

第一部分似乎按预期复制了行,你能解释一下它的作用吗?

以上是关于LEFT OUTER JOIN 不能在没有连接两边的字段相等的条件下使用的主要内容,如果未能解决你的问题,请参考以下文章

BigQuery Left Outer 出现 OR 条件错误

MySQL 数据库中 left outer join 和 left join 啥区别

SQL Server 中的 LEFT JOIN 与 LEFT OUTER JOIN

关于mysql中的left join和left outer join的区别

Oracle表与表之间的连接方式(内连接:inner join 外连接 全连接: full outer join左连接:left outer join 右连接:right outer join(代码

“,”“natural join”“natural left outer join”“natural right outer join”的用法总结