钻取:由于笛卡尔连接或不等式连接,可能无法计划此查询
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;
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;