为什么在很多递归查询中使用惰性连接类型? [重复]

问题描述 投票:0回答:1

我经常会看到正常的

JOIN
写成
CROSS JOIN
并在末尾添加
WHERE
子句,尤其是在查看
WITH RECURSIVE
文档时。例如:

a,b WHERE   (a.id=b.parent_id) -- same as: a CROSS JOIN b WHERE a.id=b.parent_id
a JOIN b ON (a.id=b.parent_id)

有任何理由这样做吗?我的想法是,查询优化器可能不会将交叉联接转换为第一个版本,因此效率可能较低。

举一个实际的例子,如下:

CREATE TABLE body AS (
    SELECT 1 id, 'body' AS name, NULL parent_id UNION ALL
    SELECT 2, 'head', 1 UNION ALL
    SELECT 3, 'eyes', 2 UNION ALL
    SELECT 4, 'pupils', 3 UNION ALL
    SELECT 5, 'torso', 1 UNION ALL
    SELECT 6, 'arms', 5
);

-- using JOIN with condition
WITH RECURSIVE body_paths (id, part, path) AS (
    SELECT id, name, name AS path FROM body WHERE parent_id IS NULL -- VALUES (1, "body", "body")
    UNION ALL
    SELECT body.id, body.name, CONCAT(path, '.', body.name) 
      FROM body JOIN body_paths ON (body.parent_id=body_paths.id)
) SELECT * FROM body_paths WHERE part in ('pupils', 'arms');

-- using CROSS JOIN + WHERE
WITH RECURSIVE body_paths (id, part, path) AS (
    SELECT id, name, name AS path FROM body WHERE parent_id IS NULL -- VALUES (1, "body", "body")
    UNION ALL
    SELECT body.id, body.name, CONCAT(path, '.', body.name) 
      FROM body, body_paths WHERE (body.parent_id=body_paths.id)
) SELECT * FROM body_paths WHERE part in ('pupils', 'arms');

-- both produce
┌────┬────────┬───────────────────────┐
│ id ┆ part   ┆ path                  │
╞════╪════════╪═══════════════════════╡
│  6 ┆ arms   ┆ body.torso.arms       │
│  4 ┆ pupils ┆ body.head.eyes.pupils │
└────┴────────┴───────────────────────┘

现在,在少于 10 行的 CTE 上,优化并不重要,但在一般情况下,应该首选非交叉连接还是为什么要以其他方式编写?

sql recursion common-table-expression
1个回答
0
投票

对于where子句,逗号连接相当于内连接。 (从技术上讲,带有 where 子句的交叉联接也相当于内部联接 - 只会输出每个表中匹配的记录,而不是两个表中的所有记录。)

就性能而言,应该没有区别,因为优化器会为其找出最佳查询计划。然而,在维护和可读性方面,逗号连接更难以阅读和理解,特别是当您向查询添加更多表时,并且正如您的问题所示,它们的行为也不太容易理解。关联哪些子句影响哪些连接也更困难。

逗号连接是一种更古老的语法,它在很大程度上已经失宠,这是有充分理由的。

© www.soinside.com 2019 - 2024. All rights reserved.