钻取:由于笛卡尔连接或不等式连接,可能无法计划此查询

Drill: This query cannot be planned possibly due to either a cartesian join or an inequality join

SELECT *
FROM hc
LEFT OUTER JOIN n
ON hc.JoinHack=n.JoinHack AND (n.`col1` IS NULL OR n.`col1`=hc.`col1`);

当 运行 在 Drill 中执行上述查询时,我收到了问题中的错误。似乎 Drill 不喜欢条件中的外部连接和 OR 的组合。

如果我进行内部联接,对虚拟列进行相等性检查的变通方法足以消除该错误(JoinHack 在我的例子中)。使用外部连接是不够的。

运行下面的查询也没有帮助:

alter session set `planner.enable_nljoin_for_scalar_only` = false;

这个问题的解决方案或好的解决方法是什么?

你可以试试 COALESCE:

SELECT *
FROM hc
LEFT OUTER JOIN n
  ON hc.JoinHack=n.JoinHack 
  AND COALESCE(n.`col1`,hc.`col1`)=hc.`col1`;

或者使用 UNION:

SELECT *
FROM hc
LEFT OUTER JOIN n
  ON hc.JoinHack=n.JoinHack 
  AND n.`col1`=hc.`col1`
UNION
SELECT *
FROM hc
LEFT OUTER JOIN n
  ON hc.JoinHack=n.JoinHack 
  AND n.`col1` IS NULL;

使用派生的 table.

select * from 
(
SELECT *
FROM hc
LEFT OUTER JOIN n
ON hc.JoinHack=n.JoinHack
) derivedTable
where n.`col1` IS NULL OR n.`col1`=hc.`col1`

这是大意。查询将抛出错误,因为 n 和 hc 在子查询之外不存在。你可以自己解决。

这是一个非常棘手的逻辑。我认为通常相当于:

SELECT *
FROM hc INNER JOIN
     n
     ON hc.JoinHack = n.JoinHack AND n.`col1` IS NULL
UNION ALL
SELECT *
FROM hc INNER JOIN
     n
     ON hc.JoinHack = n.JoinHack AND n.`col1` = hc.`col1`
UNION ALL
SELECT *
FROM hc LEFT JOIN
     n
     ON hc.JoinHack = n.JoinHack AND n.`col1` = hc.`col1`
WHERE n.JoinHack IS NULL;

Drill 接受查询的关键是将 LEFT OUTER JOIN 和包含 OR 的条件分开。因此,对子查询执行 LEFT OUTER JOIN,该子查询执行 INNER JOIN,条件包含 OR 或您想要的任何复杂逻辑。

SELECT * 
FROM hc
LEFT OUTER JOIN
(
  SELECT 
  hc.id,
  n.*
  FROM hc
  JOIN n
  ON hc.JoinHack=n.JoinHack 
    AND (n.`col1` IS NULL OR n.`col1`=hc.`col1`)
) m
ON hc.id=m.id;