Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions sqlglot/optimizer/merge_subqueries.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,14 @@ def _merge_joins(outer_scope: Scope, inner_scope: Scope, from_or_join: FromOrJoi
new_joins = []

joins = inner_scope.expression.args.get("joins") or []

outer_is_left_join = isinstance(from_or_join, exp.Join) and from_or_join.side == "LEFT"

for join in joins:
if outer_is_left_join and not join.method and join.kind in ("", "INNER"):
join.args.pop("kind", None)
join.set("side", "LEFT")

new_joins.append(join)
outer_scope.add_source(join.alias_or_name, inner_scope.sources[join.alias_or_name])

Expand Down
83 changes: 83 additions & 0 deletions tests/fixtures/optimizer/merge_subqueries.sql
Original file line number Diff line number Diff line change
Expand Up @@ -511,3 +511,86 @@ with cte as (
)
select cte.mult from cte;
SELECT x.a * x.b AS mult FROM x AS x;

# title: replace INNER JOIN with LEFT JOIN when it exists in a subquery used as the RHS of a LEFT JOIN
WITH
t0 AS (
SELECT 5 as id
),
t1 AS (
SELECT 1 AS id, 'US' AS cid
),
t2 AS (
SELECT 1 AS id, 'US' AS cid
)
SELECT
t0.id,
t3.cid AS cid
FROM t0
LEFT JOIN (
SELECT
t1.id,
t2.cid
FROM t1
INNER JOIN t2
ON t1.cid = t2.cid
) AS t3
ON t0.id = t3.id;
WITH t0 AS (SELECT 5 AS id), t1 AS (SELECT 1 AS id, 'US' AS cid), t2 AS (SELECT 1 AS id, 'US' AS cid) SELECT t0.id AS id, t2.cid AS cid FROM t0 AS t0 LEFT JOIN t1 AS t1 ON t0.id = t1.id LEFT JOIN t2 AS t2 ON t1.cid = t2.cid;

# title: preserve INNER JOIN when it exists in a subquery used as the RHS of a RIGHT JOIN
WITH
t0 AS (
SELECT 5 as id
),
t1 AS (
SELECT 1 AS id, 'US' AS cid
),
t2 AS (
SELECT 1 AS id, 'US' AS cid
)
SELECT
t0.id,
t3.cid AS cid
FROM t0
RIGHT JOIN (
SELECT
t1.id,
t2.cid
FROM t1
INNER JOIN t2
ON t1.cid = t2.cid
) AS t3
ON t0.id = t3.id;
WITH t0 AS (SELECT 5 AS id), t1 AS (SELECT 1 AS id, 'US' AS cid), t2 AS (SELECT 1 AS id, 'US' AS cid) SELECT t0.id AS id, t2.cid AS cid FROM t0 AS t0 RIGHT JOIN t1 AS t1 ON t0.id = t1.id INNER JOIN t2 AS t2 ON t1.cid = t2.cid;

# title: replace multiple INNER JOINS with LEFT JOINS when they exist in a subquery used as the RHS of a LEFT JOIN
WITH
t0 AS (
SELECT 5 as id
),
t1 AS (
SELECT 1 AS id, 'US' AS cid
),
t2 AS (
SELECT 1 AS id, 'US' AS cid
),
t3 AS (
SELECT 1 AS id, 'CA' AS cid
)
SELECT
t0.id,
t4.cid AS cid
FROM t0
LEFT JOIN (
SELECT
t1.id,
t3.cid
FROM t1
INNER JOIN t2
ON t1.cid = t2.cid
INNER JOIN t3
ON t2.id = t3.id
) AS t4
ON t0.id = t4.id;
WITH t0 AS (SELECT 5 AS id), t1 AS (SELECT 1 AS id, 'US' AS cid), t2 AS (SELECT 1 AS id, 'US' AS cid), t3 AS (SELECT 1 AS id, 'CA' AS cid) SELECT t0.id AS id, t3.cid AS cid FROM t0 AS t0 LEFT JOIN t1 AS t1 ON t0.id = t1.id LEFT JOIN t2 AS t2 ON t1.cid = t2.cid LEFT JOIN t3 AS t3 ON t2.id = t3.id;