From 5cc5b4e3aca5faab193d3daed54606a92e09aca1 Mon Sep 17 00:00:00 2001 From: guo-shaoge Date: Thu, 22 Aug 2024 13:15:19 +0800 Subject: [PATCH 1/2] This is an automated cherry-pick of #55553 Signed-off-by: ti-chi-bot --- pkg/planner/core/rule_decorrelate.go | 64 ++-- tests/integrationtest/r/cte.result | 484 +++++++++++++++++++++++++++ tests/integrationtest/t/cte.test | 345 +++++++++++++++++++ 3 files changed, 871 insertions(+), 22 deletions(-) diff --git a/pkg/planner/core/rule_decorrelate.go b/pkg/planner/core/rule_decorrelate.go index 56bb103894776..49b9543b9fbaf 100644 --- a/pkg/planner/core/rule_decorrelate.go +++ b/pkg/planner/core/rule_decorrelate.go @@ -128,29 +128,33 @@ func ExtractCorrelatedCols4PhysicalPlan(p PhysicalPlan) []*expression.Correlated // |_ Apply_3 // |_ outerSide // |_ innerSide(cor_col_3) +<<<<<<< HEAD func ExtractOuterApplyCorrelatedCols(p PhysicalPlan) []*expression.CorrelatedColumn { return extractOuterApplyCorrelatedColsHelper(p, []*expression.Schema{}) } func extractOuterApplyCorrelatedColsHelper(p PhysicalPlan, outerSchemas []*expression.Schema) []*expression.CorrelatedColumn { +======= +func ExtractOuterApplyCorrelatedCols(p base.PhysicalPlan) []*expression.CorrelatedColumn { + corCols, _ := extractOuterApplyCorrelatedColsHelper(p) + return corCols +} + +func extractOuterApplyCorrelatedColsHelper(p base.PhysicalPlan) ([]*expression.CorrelatedColumn, []*expression.Schema) { +>>>>>>> d04ec9d914a (planner: fix CTE hang or wrong result when multiple Apply is used (#55553)) if p == nil { - return nil + return nil, nil } - curCorCols := p.ExtractCorrelatedCols() - newCorCols := make([]*expression.CorrelatedColumn, 0, len(curCorCols)) - // If a corresponding Apply is found inside this PhysicalPlan, ignore it. - for _, corCol := range curCorCols { - var found bool - for _, outerSchema := range outerSchemas { - if outerSchema.ColumnIndex(&corCol.Column) != -1 { - found = true - break - } - } - if !found { - newCorCols = append(newCorCols, corCol) - } + // allCorCols store all sub plan's correlated columns. + // allOuterSchemas store all child Apply's outer side schemas. + allCorCols := p.ExtractCorrelatedCols() + allOuterSchemas := []*expression.Schema{} + + handler := func(child base.PhysicalPlan) { + childCorCols, childOuterSchemas := extractOuterApplyCorrelatedColsHelper(child) + allCorCols = append(allCorCols, childCorCols...) + allOuterSchemas = append(allOuterSchemas, childOuterSchemas...) } switch v := p.(type) { @@ -161,19 +165,35 @@ func extractOuterApplyCorrelatedColsHelper(p PhysicalPlan, outerSchemas []*expre } else { outerPlan = v.Children()[0] } - outerSchemas = append(outerSchemas, outerPlan.Schema()) - newCorCols = append(newCorCols, extractOuterApplyCorrelatedColsHelper(v.Children()[0], outerSchemas)...) - newCorCols = append(newCorCols, extractOuterApplyCorrelatedColsHelper(v.Children()[1], outerSchemas)...) + allOuterSchemas = append(allOuterSchemas, outerPlan.Schema()) + handler(v.Children()[0]) + handler(v.Children()[1]) case *PhysicalCTE: - newCorCols = append(newCorCols, extractOuterApplyCorrelatedColsHelper(v.SeedPlan, outerSchemas)...) - newCorCols = append(newCorCols, extractOuterApplyCorrelatedColsHelper(v.RecurPlan, outerSchemas)...) + handler(v.SeedPlan) + handler(v.RecurPlan) default: for _, child := range p.Children() { - newCorCols = append(newCorCols, extractOuterApplyCorrelatedColsHelper(child, outerSchemas)...) + handler(child) } } - return newCorCols + resCorCols := make([]*expression.CorrelatedColumn, 0, len(allCorCols)) + + // If one correlated column is found in allOuterSchemas, it means this correlated column is corresponding to an Apply inside `p`. + // However, we only need the correlated columns that correspond to the Apply of the parent node of `p`. + for _, corCol := range allCorCols { + var found bool + for _, outerSchema := range allOuterSchemas { + if outerSchema.ColumnIndex(&corCol.Column) != -1 { + found = true + break + } + } + if !found { + resCorCols = append(resCorCols, corCol) + } + } + return resCorCols, allOuterSchemas } // decorrelateSolver tries to convert apply plan to join plan. diff --git a/tests/integrationtest/r/cte.result b/tests/integrationtest/r/cte.result index 091ca1eb077d0..7e9954412c5c7 100644 --- a/tests/integrationtest/r/cte.result +++ b/tests/integrationtest/r/cte.result @@ -790,6 +790,7 @@ with cte1 as (select 1), cte2 as (select 2) select * from cte1 union (with cte2 1 1 3 +<<<<<<< HEAD drop table if exists t1, t2; create table t1(a int, b int); create table t2(a int, b int); @@ -797,11 +798,45 @@ insert into t1 value(5,5); insert into t2 value(1,1); with recursive cte1 as (select 1 as a union all select cte1.a+1 from t1 join cte1 on t1.a > cte1.a) select * from cte1; a +======= +drop table if exists tt, tt1, tt2, tt3, tt4, tt5; +create table tt(c1 int, c2 int); +create table tt1(c1 int, c2 int); +create table tt2(c1 int, c2 int); +create table tt3(c1 int, c2 int); +create table tt4(c1 int, c2 int); +create table tt5(c1 int, c2 int); +insert into tt values(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6); +insert into tt1 values(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6); +insert into tt2 values(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6); +insert into tt3 values(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6); +insert into tt4 values(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6); +insert into tt5 values(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6); +explain with recursive cte1 as (select c1 from tt union select c1 from cte1 where exists (select /*+ no_decorrelate() */ c1 from tt1 where tt1.c2 = cte1.c1)) select c1 from tt2 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt2.c1) order by 1; +id estRows task access object operator info +Sort_31 10000.00 root cte1.tt2.c1 +└─Apply_35 10000.00 root CARTESIAN semi join + ├─TableReader_37(Build) 10000.00 root data:TableFullScan_36 + │ └─TableFullScan_36 10000.00 cop[tikv] table:tt2 keep order:false, stats:pseudo + └─Selection_38(Probe) 64008000.00 root eq(cte1.tt.c1, cte1.tt2.c1) + └─CTEFullScan_39 80010000.00 root CTE:cte1 data:CTE_0 +CTE_0 8001.00 root Recursive CTE +├─TableReader_23(Seed Part) 10000.00 root data:TableFullScan_22 +│ └─TableFullScan_22 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +└─Apply_26(Recursive Part) 10000.00 root CARTESIAN semi join + ├─CTETable_27(Build) 10000.00 root Scan on CTE_0 + └─TableReader_30(Probe) 100000.00 root data:Selection_29 + └─Selection_29 100000.00 cop[tikv] eq(cte1.tt1.c2, cte1.tt.c1) + └─TableFullScan_28 100000000.00 cop[tikv] table:tt1 keep order:false, stats:pseudo +with recursive cte1 as (select c1 from tt union select c1 from cte1 where exists (select /*+ no_decorrelate() */ c1 from tt1 where tt1.c2 = cte1.c1)) select c1 from tt2 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt2.c1) order by 1; +c1 +>>>>>>> d04ec9d914a (planner: fix CTE hang or wrong result when multiple Apply is used (#55553)) 1 2 3 4 5 +<<<<<<< HEAD update t2 set b=2 where a in (with recursive cte1 as (select 1 as a union all select cte1.a+1 from t1 join cte1 on t1.a > cte1.a) select * from cte1); select * from t2; a b @@ -854,3 +889,452 @@ SELECT DISTINCT * FROM tree_cte1 LEFT JOIN table_abc4 e ON e.column_abc3 = aa.column_abc3 ) a ); +======= +6 +explain with recursive cte1 as (select c1 from tt union select c1 from cte1 where exists (select /*+ no_decorrelate() */ c1 from tt1 where tt1.c2 = cte1.c1)) +select c1 from tt2 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt2.c1) union select c1 from tt3 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt3.c1) union +select c1 from tt4 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt4.c1) union select c1 from tt5 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt5.c1) order by 1; +id estRows task access object operator info +Sort_58 32000.00 root Column#28 +└─HashAgg_60 32000.00 root group by:Column#28, funcs:firstrow(Column#28)->Column#28 + └─Union_61 40000.00 root + ├─Apply_64 10000.00 root CARTESIAN semi join + │ ├─TableReader_66(Build) 10000.00 root data:TableFullScan_65 + │ │ └─TableFullScan_65 10000.00 cop[tikv] table:tt2 keep order:false, stats:pseudo + │ └─Selection_67(Probe) 64008000.00 root eq(cte1.tt.c1, cte1.tt2.c1) + │ └─CTEFullScan_68 80010000.00 root CTE:cte1 data:CTE_0 + ├─Apply_71 10000.00 root CARTESIAN semi join + │ ├─TableReader_73(Build) 10000.00 root data:TableFullScan_72 + │ │ └─TableFullScan_72 10000.00 cop[tikv] table:tt3 keep order:false, stats:pseudo + │ └─Selection_74(Probe) 64008000.00 root eq(cte1.tt.c1, cte1.tt3.c1) + │ └─CTEFullScan_75 80010000.00 root CTE:cte1 data:CTE_0 + ├─Apply_78 10000.00 root CARTESIAN semi join + │ ├─TableReader_80(Build) 10000.00 root data:TableFullScan_79 + │ │ └─TableFullScan_79 10000.00 cop[tikv] table:tt4 keep order:false, stats:pseudo + │ └─Selection_81(Probe) 64008000.00 root eq(cte1.tt.c1, cte1.tt4.c1) + │ └─CTEFullScan_82 80010000.00 root CTE:cte1 data:CTE_0 + └─Apply_85 10000.00 root CARTESIAN semi join + ├─TableReader_87(Build) 10000.00 root data:TableFullScan_86 + │ └─TableFullScan_86 10000.00 cop[tikv] table:tt5 keep order:false, stats:pseudo + └─Selection_88(Probe) 64008000.00 root eq(cte1.tt.c1, cte1.tt5.c1) + └─CTEFullScan_89 80010000.00 root CTE:cte1 data:CTE_0 +CTE_0 8001.00 root Recursive CTE +├─TableReader_50(Seed Part) 10000.00 root data:TableFullScan_49 +│ └─TableFullScan_49 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +└─Apply_53(Recursive Part) 10000.00 root CARTESIAN semi join + ├─CTETable_54(Build) 10000.00 root Scan on CTE_0 + └─TableReader_57(Probe) 100000.00 root data:Selection_56 + └─Selection_56 100000.00 cop[tikv] eq(cte1.tt1.c2, cte1.tt.c1) + └─TableFullScan_55 100000000.00 cop[tikv] table:tt1 keep order:false, stats:pseudo +with recursive cte1 as (select c1 from tt union select c1 from cte1 where exists (select /*+ no_decorrelate() */ c1 from tt1 where tt1.c2 = cte1.c1)) +select c1 from tt2 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt2.c1) union select c1 from tt3 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt3.c1) union +select c1 from tt4 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt4.c1) union select c1 from tt5 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt5.c1) order by 1; +c1 +1 +2 +3 +4 +5 +6 +explain with cte1 as (with recursive cte2 as (select c1 from tt union all select c1 from cte2 where exists(select /*+ no_decorrelate() */ c1 from tt1 where tt1.c1 = cte2.c1) limit 300) +select c1 from tt union select c1 from cte2 where exists (select /*+ no_decorrelate() */ c1 from tt1 where tt1.c2 = cte2.c1)) +select c1 from tt2 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt2.c1) union select c1 from tt3 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt3.c1) union +select c1 from tt4 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt4.c1) union select c1 from tt5 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt5.c1) order by 1; +id estRows task access object operator info +Sort_85 32000.00 root Column#36 +└─HashAgg_87 32000.00 root group by:Column#36, funcs:firstrow(Column#36)->Column#36 + └─Union_88 40000.00 root + ├─Apply_91 10000.00 root CARTESIAN semi join + │ ├─TableReader_93(Build) 10000.00 root data:TableFullScan_92 + │ │ └─TableFullScan_92 10000.00 cop[tikv] table:tt2 keep order:false, stats:pseudo + │ └─Selection_94(Probe) 128008000.00 root eq(Column#23, cte1.tt2.c1) + │ └─CTEFullScan_95 160010000.00 root CTE:cte1 data:CTE_0 + ├─Apply_98 10000.00 root CARTESIAN semi join + │ ├─TableReader_100(Build) 10000.00 root data:TableFullScan_99 + │ │ └─TableFullScan_99 10000.00 cop[tikv] table:tt3 keep order:false, stats:pseudo + │ └─Selection_101(Probe) 128008000.00 root eq(Column#27, cte1.tt3.c1) + │ └─CTEFullScan_102 160010000.00 root CTE:cte1 data:CTE_0 + ├─Apply_105 10000.00 root CARTESIAN semi join + │ ├─TableReader_107(Build) 10000.00 root data:TableFullScan_106 + │ │ └─TableFullScan_106 10000.00 cop[tikv] table:tt4 keep order:false, stats:pseudo + │ └─Selection_108(Probe) 128008000.00 root eq(Column#31, cte1.tt4.c1) + │ └─CTEFullScan_109 160010000.00 root CTE:cte1 data:CTE_0 + └─Apply_112 10000.00 root CARTESIAN semi join + ├─TableReader_114(Build) 10000.00 root data:TableFullScan_113 + │ └─TableFullScan_113 10000.00 cop[tikv] table:tt5 keep order:false, stats:pseudo + └─Selection_115(Probe) 128008000.00 root eq(Column#35, cte1.tt5.c1) + └─CTEFullScan_116 160010000.00 root CTE:cte1 data:CTE_0 +CTE_0 16001.00 root Non-Recursive CTE +└─HashAgg_73(Seed Part) 16001.00 root group by:Column#19, funcs:firstrow(Column#19)->Column#19 + └─Union_74 30000.00 root + ├─TableReader_77 10000.00 root data:TableFullScan_76 + │ └─TableFullScan_76 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo + └─Apply_80 20000.00 root CARTESIAN semi join + ├─CTEFullScan_81(Build) 20000.00 root CTE:cte2 data:CTE_1 + └─TableReader_84(Probe) 200000.00 root data:Selection_83 + └─Selection_83 200000.00 cop[tikv] eq(cte1.tt1.c2, cte1.tt.c1) + └─TableFullScan_82 200000000.00 cop[tikv] table:tt1 keep order:false, stats:pseudo +CTE_1 20000.00 root Recursive CTE, limit(offset:0, count:300) +├─TableReader_65(Seed Part) 10000.00 root data:TableFullScan_64 +│ └─TableFullScan_64 10000.00 cop[tikv] table:tt keep order:false, stats:pseudo +└─Apply_68(Recursive Part) 10000.00 root CARTESIAN semi join + ├─CTETable_69(Build) 10000.00 root Scan on CTE_1 + └─TableReader_72(Probe) 100000.00 root data:Selection_71 + └─Selection_71 100000.00 cop[tikv] eq(cte1.tt1.c1, cte1.tt.c1) + └─TableFullScan_70 100000000.00 cop[tikv] table:tt1 keep order:false, stats:pseudo +with cte1 as (with recursive cte2 as (select c1 from tt union all select c1 from cte2 where exists(select /*+ no_decorrelate() */ c1 from tt1 where tt1.c1 = cte2.c1) limit 300) +select c1 from tt union select c1 from cte2 where exists (select /*+ no_decorrelate() */ c1 from tt1 where tt1.c2 = cte2.c1)) +select c1 from tt2 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt2.c1) union select c1 from tt3 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt3.c1) union +select c1 from tt4 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt4.c1) union select c1 from tt5 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt5.c1) order by 1; +c1 +1 +2 +3 +4 +5 +6 +drop table if exists table_a, table_b, table_c, table_d, table_e; +CREATE TABLE `table_a` ( +`col_1` varchar(40) DEFAULT NULL, +`col_2` varchar(40) DEFAULT NULL, +`col_3` varchar(500) DEFAULT NULL, +`col_4` varchar(500) DEFAULT NULL, +`col_5` varchar(500) DEFAULT NULL, +`col_6` varchar(500) DEFAULT NULL, +`col_7` decimal(38,6) DEFAULT NULL, +`col_8` decimal(38,6) DEFAULT NULL, +`col_9` decimal(38,6) DEFAULT NULL, +`col_10` decimal(38,6) DEFAULT NULL, +`col_11` decimal(38,6) DEFAULT NULL, +`col_12` decimal(38,6) DEFAULT NULL, +`col_13` decimal(38,6) DEFAULT NULL, +`col_14` decimal(38,6) DEFAULT NULL, +`col_15` decimal(38,6) DEFAULT NULL, +`col_16` decimal(38,6) DEFAULT NULL, +`col_17` decimal(38,6) DEFAULT NULL, +`col_18` decimal(38,6) DEFAULT NULL, +`col_19` varchar(40) DEFAULT NULL, +`col_20` varchar(100) DEFAULT NULL, +`col_21` varchar(100) DEFAULT NULL, +`created_at` timestamp DEFAULT CURRENT_TIMESTAMP, +KEY `index_col_1` (`col_1`), +KEY `index_col_2_3` (`col_2`,`col_3`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; +CREATE TABLE `table_b` ( +`col_1` varchar(8) NOT NULL, +`col_2` varchar(100) NOT NULL, +`col_3` varchar(200) DEFAULT NULL, +`col_4` varchar(10) NOT NULL, +`col_5` decimal(38,6) DEFAULT NULL, +`col_6` decimal(38,6) DEFAULT NULL, +`col_7` decimal(38,6) DEFAULT NULL, +`col_8` decimal(38,6) DEFAULT NULL, +`created_at` datetime DEFAULT CURRENT_TIMESTAMP, +KEY `index_col_1_2` (`col_1`,`col_2`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; +CREATE TABLE `table_c` ( +`col_1` varchar(50) DEFAULT NULL, +`col_2` varchar(50) DEFAULT NULL, +`col_3` varchar(30) DEFAULT NULL, +`col_4` varchar(100) DEFAULT NULL, +`col_5` varchar(50) DEFAULT NULL, +`col_6` varchar(100) DEFAULT NULL, +`col_7` decimal(38,6) DEFAULT NULL, +`col_8` decimal(38,6) DEFAULT NULL, +`col_9` decimal(38,6) DEFAULT NULL, +`col_10` decimal(38,6) DEFAULT NULL, +`col_11` decimal(38,6) DEFAULT NULL, +`col_12` decimal(38,6) DEFAULT NULL, +`col_13` decimal(38,6) DEFAULT NULL, +`col_14` decimal(38,6) DEFAULT NULL, +`col_15` decimal(38,6) DEFAULT NULL, +`col_16` decimal(38,6) DEFAULT NULL, +`col_17` varchar(50) DEFAULT NULL, +`col_18` varchar(50) DEFAULT NULL, +`col_19` varchar(50) DEFAULT NULL, +`created_at` timestamp DEFAULT CURRENT_TIMESTAMP, +KEY `index_col_1_3` (`col_1`,`col_3`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; +CREATE TABLE `table_d` ( +`col_1` decimal(10,0) DEFAULT NULL, +`col_2` varchar(1) DEFAULT NULL, +`col_3` date NOT NULL, +`col_4` varchar(13) DEFAULT NULL, +`col_5` varchar(6) DEFAULT NULL, +`col_6` varchar(255) DEFAULT NULL, +`col_7` decimal(10,0) DEFAULT NULL, +`col_8` varchar(12) DEFAULT NULL, +`col_9` decimal(10,0) DEFAULT NULL, +`col_10` varchar(17) DEFAULT NULL, +`col_11` decimal(10,0) DEFAULT NULL, +`col_12` varchar(7) DEFAULT NULL, +`col_13` date DEFAULT NULL, +`col_14` date DEFAULT NULL, +`col_15` date DEFAULT NULL, +`col_16` date DEFAULT NULL, +`col_17` date DEFAULT NULL, +`col_18` date DEFAULT NULL, +`col_19` date DEFAULT NULL, +`col_20` varchar(1) DEFAULT NULL, +`col_21` varchar(1) DEFAULT NULL, +`col_22` decimal(1,0) DEFAULT NULL, +`col_23` varchar(1) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; +CREATE TABLE `table_e` ( +`col_1` varchar(8) NOT NULL, +`col_2` varchar(100) NOT NULL, +`col_3` varchar(100) DEFAULT NULL, +`col_4` varchar(100) NOT NULL, +`col_5` varchar(100) DEFAULT NULL, +`col_6` varchar(100) DEFAULT NULL, +`col_7` decimal(38,12) DEFAULT NULL, +`col_8` varchar(100) DEFAULT NULL, +`col_9` varchar(100) DEFAULT NULL, +`col_10` varchar(100) DEFAULT NULL, +`col_11` varchar(100) DEFAULT NULL, +`col_12` varchar(8) DEFAULT NULL, +`col_13` decimal(38,12) DEFAULT NULL, +`col_14` varchar(100) DEFAULT NULL, +`created_at` timestamp DEFAULT CURRENT_TIMESTAMP, +`col_15` varchar(500) DEFAULT NULL, +PRIMARY KEY (`col_2`, `col_1`, `col_4`), +KEY `index_col_5_6` (`col_5`, `col_6`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; +INSERT INTO `table_a` +(`col_1`, `col_2`, `col_3`, `col_4`, `col_5`, `col_6`, `col_7`, +`col_8`, `col_9`, `col_10`, `col_11`, `col_12`, `col_13`, +`col_14`, `col_15`, `col_16`, `col_17`, `col_18`, `col_19`, +`col_20`, `col_21`, `created_at`) +VALUES +('20230628', '20230628', 'Portfolio A', 'Product B', 'Direct', 'USD', +200000, 150000, 50000, 100000, +50000, 10000, 5000, 1.2, 0.1, +0.15, 0.08, 0.02, '2023-06-28', +'2023-06-28', '2025-06-28', CURRENT_TIMESTAMP); +INSERT INTO `table_b` +(`col_1`, `col_2`, `col_3`, `col_4`, `col_5`, `col_6`, `col_7`, `col_8`, `created_at`) +VALUES +('20240628', 'DR201800093', 'Product A', '申购', 1000, 100000, 95000, 1.1, CURRENT_TIMESTAMP); +INSERT INTO `table_c` +(`col_1`, `col_2`, `col_3`, `col_4`, `col_5`, `col_6`, `col_7`, +`col_8`, `col_9`, `col_10`, `col_11`, `col_12`, `col_13`, +`col_14`, `col_15`, `col_16`, `col_17`, `col_18`, `col_19`, `created_at`) +VALUES +('20230628', 'Dept A', 'DR201800093', 'Product A', '孵化', 'Strategy 1', +100000, 100000, 120000, 100, 1.2, +0.2, 0.15, 0.1, 0.05, 0.08, +'2023-06-28', '2025-06-28', '2Y', CURRENT_TIMESTAMP); +INSERT INTO `table_d` +(`col_1`, `col_2`, `col_3`, `col_4`, `col_5`, `col_6`, `col_7`, +`col_8`, `col_9`, `col_10`, `col_11`, `col_12`, `col_13`, `col_14`, +`col_15`, `col_16`, `col_17`, `col_18`, `col_19`, `col_20`, `col_21`, +`col_22`, `col_23`) +VALUES +('20240628', '1', '2024-06-28', 'Friday', '28', 'End of Month', 202406, +'June', 20242, 'Q2', 2024, '2024', '2024-06-27', '2024-05-28', +'2024-03-28', '2023-06-28', '2024-06-27', '2024-06-27', '2024-06-27', +'1', '1', '1', '1'); +INSERT INTO `table_e` +(`col_1`, `col_2`, `col_3`, `col_4`, `col_5`, `col_6`, `col_7`, +`col_8`, `col_9`, `col_10`, `col_11`, `col_12`, `col_13`, `col_14`, +`created_at`, `col_15`) +VALUES +('20230628', 'CFETS_MID', 'Mid', 'USD/CNY', 'USD', 'CNY', +7.0, 'Source A', 'Unit A', 'Region A', '2023-06-28 15:00:00', '20230627', +6.9, 'user_001', CURRENT_TIMESTAMP, 'Exchange rate on 2023-06-28'); +desc WITH date_table AS ( +SELECT +d.col_1 AS date, +(SELECT MAX(col_1) +FROM table_c a +WHERE col_1 <= +CONCAT(YEAR(DATE_SUB(d.col_1, INTERVAL 1 YEAR)), +'1231') +AND EXISTS (SELECT 1 +FROM table_d d +WHERE a.col_1 = d.col_1 +AND d.col_2 = 1)) AS date1, +(SELECT MAX(col_1) +FROM table_a a +WHERE col_1 <= CONCAT(YEAR(DATE_SUB(d.col_1, INTERVAL 1 YEAR)), +'1231') +AND EXISTS (SELECT 1 +FROM table_d d +WHERE a.col_1 = d.col_1 +AND d.col_2 = 1)) AS date2, +(SELECT MAX(col_1) +FROM table_c +WHERE col_1 <= d.col_1) AS date3, +(SELECT MAX(col_1) +FROM table_a +WHERE col_1 <= d.col_1) AS date4 +FROM table_d d +WHERE d.col_1 = '20240628' +), +rm_am_champs_ex_risk_portfolio_seed_money_1 AS ( +SELECT b.col_2 +FROM table_a b +LEFT JOIN table_e rb +ON rb.col_1 = b.col_19 +AND b.col_6 = rb.col_3 +WHERE b.col_2 = (SELECT date4 FROM date_table) +), +rm_am_champs_ex_risk_portfolio_seed_money_2 AS ( +SELECT b.col_2 +FROM table_a b +LEFT JOIN table_e rb +ON rb.col_1 = b.col_19 +AND b.col_6 = rb.col_3 +), +product_base AS ( +SELECT DISTINCT t.col_3, col_4, 'ML' AS is_do +FROM table_c t +), +product_detail AS ( +SELECT t.col_4, +"3集合" AS nature_investment +FROM product_base t +LEFT JOIN date_table dt +ON 1 = 1 +LEFT JOIN table_c a +ON t.col_4 = a.col_4 +AND a.col_1 = dt.date3 +) +SELECT col_4 +FROM ( +SELECT col_4 +FROM product_detail +UNION ALL +SELECT col_4 +FROM product_detail +) a; +id estRows task access object operator info +Union_212 199600.20 root +├─Projection_213 99800.10 root cte1.table_c.col_4->Column#418 +│ └─CTEFullScan_214 99800.10 root CTE:product_detail data:CTE_4 +└─Projection_215 99800.10 root cte1.table_c.col_4->Column#418 + └─CTEFullScan_216 99800.10 root CTE:product_detail data:CTE_4 +CTE_4 99800.10 root Non-Recursive CTE +└─Projection_174(Seed Part) 99800.10 root cte1.table_c.col_4, 3集合->Column#413 + └─HashJoin_190 99800.10 root left outer join, equal:[eq(cte1.table_c.col_4, cte1.table_c.col_4) eq(Column#390, cte1.table_c.col_1)] + ├─TableReader_206(Build) 9980.01 root data:Selection_205 + │ └─Selection_205 9980.01 cop[tikv] not(isnull(cte1.table_c.col_1)), not(isnull(cte1.table_c.col_4)) + │ └─TableFullScan_204 10000.00 cop[tikv] table:a keep order:false, stats:pseudo + └─HashJoin_192(Probe) 80000.00 root CARTESIAN left outer join + ├─CTEFullScan_202(Build) 10.00 root CTE:date_table AS dt data:CTE_0 + └─HashAgg_198(Probe) 8000.00 root group by:cte1.table_c.col_3, cte1.table_c.col_4, funcs:firstrow(cte1.table_c.col_4)->cte1.table_c.col_4 + └─TableReader_199 8000.00 root data:HashAgg_194 + └─HashAgg_194 8000.00 cop[tikv] group by:cte1.table_c.col_3, cte1.table_c.col_4, + └─TableFullScan_197 10000.00 cop[tikv] table:t keep order:false, stats:pseudo +CTE_0 10.00 root Non-Recursive CTE +└─Apply_97(Seed Part) 10.00 root CARTESIAN left outer join + ├─Apply_99(Build) 10.00 root CARTESIAN left outer join + │ ├─Apply_101(Build) 10.00 root CARTESIAN left outer join + │ │ ├─Apply_103(Build) 10.00 root CARTESIAN left outer join + │ │ │ ├─TableReader_106(Build) 10.00 root data:Selection_105 + │ │ │ │ └─Selection_105 10.00 cop[tikv] eq(cte1.table_d.col_1, 20240628) + │ │ │ │ └─TableFullScan_104 10000.00 cop[tikv] table:d keep order:false, stats:pseudo + │ │ │ └─StreamAgg_108(Probe) 10.00 root funcs:max(cte1.table_c.col_1)->Column#159 + │ │ │ └─TopN_111 10.00 root cte1.table_c.col_1:desc, offset:0, count:1 + │ │ │ └─HashJoin_116 63936.00 root semi join, equal:[eq(Column#423, Column#424)] + │ │ │ ├─Projection_121(Build) 80000.00 root cast(cte1.table_d.col_1, double BINARY)->Column#424 + │ │ │ │ └─TableReader_124 80000.00 root data:Selection_123 + │ │ │ │ └─Selection_123 80000.00 cop[tikv] eq(cast(cte1.table_d.col_2, double BINARY), 1) + │ │ │ │ └─TableFullScan_122 100000.00 cop[tikv] table:d keep order:false, stats:pseudo + │ │ │ └─Projection_117(Probe) 79920.00 root cte1.table_c.col_1, cast(cte1.table_c.col_1, double BINARY)->Column#423 + │ │ │ └─Selection_118 79920.00 root le(cte1.table_c.col_1, concat(cast(year(cast(date_sub(cte1.table_d.col_1, 1, "YEAR"), datetime(6) BINARY)), var_string(20)), "1231")) + │ │ │ └─IndexReader_120 99900.00 root index:IndexFullScan_119 + │ │ │ └─IndexFullScan_119 99900.00 cop[tikv] table:a, index:index_col_1_3(col_1, col_3) keep order:false, stats:pseudo + │ │ └─StreamAgg_126(Probe) 10.00 root funcs:max(cte1.table_a.col_1)->Column#208 + │ │ └─TopN_129 10.00 root cte1.table_a.col_1:desc, offset:0, count:1 + │ │ └─HashJoin_134 63936.00 root semi join, equal:[eq(Column#429, Column#430)] + │ │ ├─Projection_139(Build) 80000.00 root cast(cte1.table_d.col_1, double BINARY)->Column#430 + │ │ │ └─TableReader_142 80000.00 root data:Selection_141 + │ │ │ └─Selection_141 80000.00 cop[tikv] eq(cast(cte1.table_d.col_2, double BINARY), 1) + │ │ │ └─TableFullScan_140 100000.00 cop[tikv] table:d keep order:false, stats:pseudo + │ │ └─Projection_135(Probe) 79920.00 root cte1.table_a.col_1, cast(cte1.table_a.col_1, double BINARY)->Column#429 + │ │ └─Selection_136 79920.00 root le(cte1.table_a.col_1, concat(cast(year(cast(date_sub(cte1.table_d.col_1, 1, "YEAR"), datetime(6) BINARY)), var_string(20)), "1231")) + │ │ └─IndexReader_138 99900.00 root index:IndexFullScan_137 + │ │ └─IndexFullScan_137 99900.00 cop[tikv] table:a, index:index_col_1(col_1) keep order:false, stats:pseudo + │ └─StreamAgg_144(Probe) 10.00 root funcs:max(cte1.table_c.col_1)->Column#230 + │ └─Limit_148 10.00 root offset:0, count:1 + │ └─IndexReader_157 10.00 root index:Limit_156 + │ └─Limit_156 10.00 cop[tikv] offset:0, count:1 + │ └─Selection_155 10.00 cop[tikv] le(cast(cte1.table_c.col_1, double BINARY), cast(cte1.table_d.col_1, double BINARY)) + │ └─IndexFullScan_154 12.50 cop[tikv] table:table_c, index:index_col_1_3(col_1, col_3) keep order:true, desc, stats:pseudo + └─StreamAgg_159(Probe) 10.00 root funcs:max(cte1.table_a.col_1)->Column#254 + └─Limit_163 10.00 root offset:0, count:1 + └─IndexReader_172 10.00 root index:Limit_171 + └─Limit_171 10.00 cop[tikv] offset:0, count:1 + └─Selection_170 10.00 cop[tikv] le(cast(cte1.table_a.col_1, double BINARY), cast(cte1.table_d.col_1, double BINARY)) + └─IndexFullScan_169 12.50 cop[tikv] table:table_a, index:index_col_1(col_1) keep order:true, desc, stats:pseudo +WITH date_table AS ( +SELECT +d.col_1 AS date, +(SELECT MAX(col_1) +FROM table_c a +WHERE col_1 <= +CONCAT(YEAR(DATE_SUB(d.col_1, INTERVAL 1 YEAR)), +'1231') +AND EXISTS (SELECT 1 +FROM table_d d +WHERE a.col_1 = d.col_1 +AND d.col_2 = 1)) AS date1, +(SELECT MAX(col_1) +FROM table_a a +WHERE col_1 <= CONCAT(YEAR(DATE_SUB(d.col_1, INTERVAL 1 YEAR)), +'1231') +AND EXISTS (SELECT 1 +FROM table_d d +WHERE a.col_1 = d.col_1 +AND d.col_2 = 1)) AS date2, +(SELECT MAX(col_1) +FROM table_c +WHERE col_1 <= d.col_1) AS date3, +(SELECT MAX(col_1) +FROM table_a +WHERE col_1 <= d.col_1) AS date4 +FROM table_d d +WHERE d.col_1 = '20240628' +), +rm_am_champs_ex_risk_portfolio_seed_money_1 AS ( +SELECT b.col_2 +FROM table_a b +LEFT JOIN table_e rb +ON rb.col_1 = b.col_19 +AND b.col_6 = rb.col_3 +WHERE b.col_2 = (SELECT date4 FROM date_table) +), +rm_am_champs_ex_risk_portfolio_seed_money_2 AS ( +SELECT b.col_2 +FROM table_a b +LEFT JOIN table_e rb +ON rb.col_1 = b.col_19 +AND b.col_6 = rb.col_3 +), +product_base AS ( +SELECT DISTINCT t.col_3, col_4, 'ML' AS is_do +FROM table_c t +), +product_detail AS ( +SELECT t.col_4, +"3集合" AS nature_investment +FROM product_base t +LEFT JOIN date_table dt +ON 1 = 1 +LEFT JOIN table_c a +ON t.col_4 = a.col_4 +AND a.col_1 = dt.date3 +) +SELECT col_4 +FROM ( +SELECT col_4 +FROM product_detail +UNION ALL +SELECT col_4 +FROM product_detail +) a; +col_4 +Product A +Product A +>>>>>>> d04ec9d914a (planner: fix CTE hang or wrong result when multiple Apply is used (#55553)) diff --git a/tests/integrationtest/t/cte.test b/tests/integrationtest/t/cte.test index bfef25d231d65..c986c31e15c41 100644 --- a/tests/integrationtest/t/cte.test +++ b/tests/integrationtest/t/cte.test @@ -337,6 +337,7 @@ WITH cte_0 AS (select distinct ref_0.wkey as c0, ref_0.pkey as c1, ref_0.c_xhsnd #case with cte1 as (select 1), cte2 as (select 2) select * from cte1 union (with cte2 as (select 3) select * from cte2 union all select * from cte2) order by 1; +<<<<<<< HEAD # Tests for PR #55732 drop table if exists t1, t2; create table t1(a int, b int); @@ -403,4 +404,348 @@ WHERE t_abc3.column_abc5 IN ( ) a ); +======= +# case: test CTE with complicated Apply and other operators +drop table if exists tt, tt1, tt2, tt3, tt4, tt5; +create table tt(c1 int, c2 int); +create table tt1(c1 int, c2 int); +create table tt2(c1 int, c2 int); +create table tt3(c1 int, c2 int); +create table tt4(c1 int, c2 int); +create table tt5(c1 int, c2 int); +insert into tt values(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6); +insert into tt1 values(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6); +insert into tt2 values(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6); +insert into tt3 values(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6); +insert into tt4 values(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6); +insert into tt5 values(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6); + +## sub case-1: CTE with Apply +explain with recursive cte1 as (select c1 from tt union select c1 from cte1 where exists (select /*+ no_decorrelate() */ c1 from tt1 where tt1.c2 = cte1.c1)) select c1 from tt2 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt2.c1) order by 1; + +with recursive cte1 as (select c1 from tt union select c1 from cte1 where exists (select /*+ no_decorrelate() */ c1 from tt1 where tt1.c2 = cte1.c1)) select c1 from tt2 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt2.c1) order by 1; + +## sub case-2: CTE with Apply and Union +explain with recursive cte1 as (select c1 from tt union select c1 from cte1 where exists (select /*+ no_decorrelate() */ c1 from tt1 where tt1.c2 = cte1.c1)) +select c1 from tt2 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt2.c1) union select c1 from tt3 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt3.c1) union +select c1 from tt4 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt4.c1) union select c1 from tt5 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt5.c1) order by 1; + +with recursive cte1 as (select c1 from tt union select c1 from cte1 where exists (select /*+ no_decorrelate() */ c1 from tt1 where tt1.c2 = cte1.c1)) +select c1 from tt2 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt2.c1) union select c1 from tt3 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt3.c1) union +select c1 from tt4 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt4.c1) union select c1 from tt5 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt5.c1) order by 1; + +## sub case-3: nested CTE with Apply and union +explain with cte1 as (with recursive cte2 as (select c1 from tt union all select c1 from cte2 where exists(select /*+ no_decorrelate() */ c1 from tt1 where tt1.c1 = cte2.c1) limit 300) +select c1 from tt union select c1 from cte2 where exists (select /*+ no_decorrelate() */ c1 from tt1 where tt1.c2 = cte2.c1)) +select c1 from tt2 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt2.c1) union select c1 from tt3 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt3.c1) union +select c1 from tt4 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt4.c1) union select c1 from tt5 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt5.c1) order by 1; + +with cte1 as (with recursive cte2 as (select c1 from tt union all select c1 from cte2 where exists(select /*+ no_decorrelate() */ c1 from tt1 where tt1.c1 = cte2.c1) limit 300) +select c1 from tt union select c1 from cte2 where exists (select /*+ no_decorrelate() */ c1 from tt1 where tt1.c2 = cte2.c1)) +select c1 from tt2 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt2.c1) union select c1 from tt3 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt3.c1) union +select c1 from tt4 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt4.c1) union select c1 from tt5 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt5.c1) order by 1; + +## sub case-4: simplified user query +drop table if exists table_a, table_b, table_c, table_d, table_e; +CREATE TABLE `table_a` ( + `col_1` varchar(40) DEFAULT NULL, + `col_2` varchar(40) DEFAULT NULL, + `col_3` varchar(500) DEFAULT NULL, + `col_4` varchar(500) DEFAULT NULL, + `col_5` varchar(500) DEFAULT NULL, + `col_6` varchar(500) DEFAULT NULL, + `col_7` decimal(38,6) DEFAULT NULL, + `col_8` decimal(38,6) DEFAULT NULL, + `col_9` decimal(38,6) DEFAULT NULL, + `col_10` decimal(38,6) DEFAULT NULL, + `col_11` decimal(38,6) DEFAULT NULL, + `col_12` decimal(38,6) DEFAULT NULL, + `col_13` decimal(38,6) DEFAULT NULL, + `col_14` decimal(38,6) DEFAULT NULL, + `col_15` decimal(38,6) DEFAULT NULL, + `col_16` decimal(38,6) DEFAULT NULL, + `col_17` decimal(38,6) DEFAULT NULL, + `col_18` decimal(38,6) DEFAULT NULL, + `col_19` varchar(40) DEFAULT NULL, + `col_20` varchar(100) DEFAULT NULL, + `col_21` varchar(100) DEFAULT NULL, + `created_at` timestamp DEFAULT CURRENT_TIMESTAMP, + KEY `index_col_1` (`col_1`), + KEY `index_col_2_3` (`col_2`,`col_3`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + + +CREATE TABLE `table_b` ( + `col_1` varchar(8) NOT NULL, + `col_2` varchar(100) NOT NULL, + `col_3` varchar(200) DEFAULT NULL, + `col_4` varchar(10) NOT NULL, + `col_5` decimal(38,6) DEFAULT NULL, + `col_6` decimal(38,6) DEFAULT NULL, + `col_7` decimal(38,6) DEFAULT NULL, + `col_8` decimal(38,6) DEFAULT NULL, + `created_at` datetime DEFAULT CURRENT_TIMESTAMP, + KEY `index_col_1_2` (`col_1`,`col_2`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + +CREATE TABLE `table_c` ( + `col_1` varchar(50) DEFAULT NULL, + `col_2` varchar(50) DEFAULT NULL, + `col_3` varchar(30) DEFAULT NULL, + `col_4` varchar(100) DEFAULT NULL, + `col_5` varchar(50) DEFAULT NULL, + `col_6` varchar(100) DEFAULT NULL, + `col_7` decimal(38,6) DEFAULT NULL, + `col_8` decimal(38,6) DEFAULT NULL, + `col_9` decimal(38,6) DEFAULT NULL, + `col_10` decimal(38,6) DEFAULT NULL, + `col_11` decimal(38,6) DEFAULT NULL, + `col_12` decimal(38,6) DEFAULT NULL, + `col_13` decimal(38,6) DEFAULT NULL, + `col_14` decimal(38,6) DEFAULT NULL, + `col_15` decimal(38,6) DEFAULT NULL, + `col_16` decimal(38,6) DEFAULT NULL, + `col_17` varchar(50) DEFAULT NULL, + `col_18` varchar(50) DEFAULT NULL, + `col_19` varchar(50) DEFAULT NULL, + `created_at` timestamp DEFAULT CURRENT_TIMESTAMP, + KEY `index_col_1_3` (`col_1`,`col_3`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + +CREATE TABLE `table_d` ( + `col_1` decimal(10,0) DEFAULT NULL, + `col_2` varchar(1) DEFAULT NULL, + `col_3` date NOT NULL, + `col_4` varchar(13) DEFAULT NULL, + `col_5` varchar(6) DEFAULT NULL, + `col_6` varchar(255) DEFAULT NULL, + `col_7` decimal(10,0) DEFAULT NULL, + `col_8` varchar(12) DEFAULT NULL, + `col_9` decimal(10,0) DEFAULT NULL, + `col_10` varchar(17) DEFAULT NULL, + `col_11` decimal(10,0) DEFAULT NULL, + `col_12` varchar(7) DEFAULT NULL, + `col_13` date DEFAULT NULL, + `col_14` date DEFAULT NULL, + `col_15` date DEFAULT NULL, + `col_16` date DEFAULT NULL, + `col_17` date DEFAULT NULL, + `col_18` date DEFAULT NULL, + `col_19` date DEFAULT NULL, + `col_20` varchar(1) DEFAULT NULL, + `col_21` varchar(1) DEFAULT NULL, + `col_22` decimal(1,0) DEFAULT NULL, + `col_23` varchar(1) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + +CREATE TABLE `table_e` ( + `col_1` varchar(8) NOT NULL, + `col_2` varchar(100) NOT NULL, + `col_3` varchar(100) DEFAULT NULL, + `col_4` varchar(100) NOT NULL, + `col_5` varchar(100) DEFAULT NULL, + `col_6` varchar(100) DEFAULT NULL, + `col_7` decimal(38,12) DEFAULT NULL, + `col_8` varchar(100) DEFAULT NULL, + `col_9` varchar(100) DEFAULT NULL, + `col_10` varchar(100) DEFAULT NULL, + `col_11` varchar(100) DEFAULT NULL, + `col_12` varchar(8) DEFAULT NULL, + `col_13` decimal(38,12) DEFAULT NULL, + `col_14` varchar(100) DEFAULT NULL, + `created_at` timestamp DEFAULT CURRENT_TIMESTAMP, + `col_15` varchar(500) DEFAULT NULL, + PRIMARY KEY (`col_2`, `col_1`, `col_4`), + KEY `index_col_5_6` (`col_5`, `col_6`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + +INSERT INTO `table_a` +(`col_1`, `col_2`, `col_3`, `col_4`, `col_5`, `col_6`, `col_7`, + `col_8`, `col_9`, `col_10`, `col_11`, `col_12`, `col_13`, + `col_14`, `col_15`, `col_16`, `col_17`, `col_18`, `col_19`, + `col_20`, `col_21`, `created_at`) +VALUES +('20230628', '20230628', 'Portfolio A', 'Product B', 'Direct', 'USD', + 200000, 150000, 50000, 100000, + 50000, 10000, 5000, 1.2, 0.1, + 0.15, 0.08, 0.02, '2023-06-28', + '2023-06-28', '2025-06-28', CURRENT_TIMESTAMP); + + INSERT INTO `table_b` +(`col_1`, `col_2`, `col_3`, `col_4`, `col_5`, `col_6`, `col_7`, `col_8`, `created_at`) +VALUES +('20240628', 'DR201800093', 'Product A', '申购', 1000, 100000, 95000, 1.1, CURRENT_TIMESTAMP); + +INSERT INTO `table_c` +(`col_1`, `col_2`, `col_3`, `col_4`, `col_5`, `col_6`, `col_7`, + `col_8`, `col_9`, `col_10`, `col_11`, `col_12`, `col_13`, + `col_14`, `col_15`, `col_16`, `col_17`, `col_18`, `col_19`, `created_at`) +VALUES +('20230628', 'Dept A', 'DR201800093', 'Product A', '孵化', 'Strategy 1', + 100000, 100000, 120000, 100, 1.2, + 0.2, 0.15, 0.1, 0.05, 0.08, + '2023-06-28', '2025-06-28', '2Y', CURRENT_TIMESTAMP); + +INSERT INTO `table_d` +(`col_1`, `col_2`, `col_3`, `col_4`, `col_5`, `col_6`, `col_7`, + `col_8`, `col_9`, `col_10`, `col_11`, `col_12`, `col_13`, `col_14`, + `col_15`, `col_16`, `col_17`, `col_18`, `col_19`, `col_20`, `col_21`, + `col_22`, `col_23`) +VALUES +('20240628', '1', '2024-06-28', 'Friday', '28', 'End of Month', 202406, + 'June', 20242, 'Q2', 2024, '2024', '2024-06-27', '2024-05-28', + '2024-03-28', '2023-06-28', '2024-06-27', '2024-06-27', '2024-06-27', + '1', '1', '1', '1'); + + INSERT INTO `table_e` +(`col_1`, `col_2`, `col_3`, `col_4`, `col_5`, `col_6`, `col_7`, + `col_8`, `col_9`, `col_10`, `col_11`, `col_12`, `col_13`, `col_14`, + `created_at`, `col_15`) +VALUES +('20230628', 'CFETS_MID', 'Mid', 'USD/CNY', 'USD', 'CNY', + 7.0, 'Source A', 'Unit A', 'Region A', '2023-06-28 15:00:00', '20230627', + 6.9, 'user_001', CURRENT_TIMESTAMP, 'Exchange rate on 2023-06-28'); + +desc WITH date_table AS ( + SELECT + d.col_1 AS date, + (SELECT MAX(col_1) + FROM table_c a + WHERE col_1 <= + CONCAT(YEAR(DATE_SUB(d.col_1, INTERVAL 1 YEAR)), + '1231') + AND EXISTS (SELECT 1 + FROM table_d d + WHERE a.col_1 = d.col_1 + AND d.col_2 = 1)) AS date1, + (SELECT MAX(col_1) + FROM table_a a + WHERE col_1 <= CONCAT(YEAR(DATE_SUB(d.col_1, INTERVAL 1 YEAR)), + '1231') + AND EXISTS (SELECT 1 + FROM table_d d + WHERE a.col_1 = d.col_1 + AND d.col_2 = 1)) AS date2, + (SELECT MAX(col_1) + FROM table_c + WHERE col_1 <= d.col_1) AS date3, + (SELECT MAX(col_1) + FROM table_a + WHERE col_1 <= d.col_1) AS date4 + FROM table_d d + WHERE d.col_1 = '20240628' +), +rm_am_champs_ex_risk_portfolio_seed_money_1 AS ( + SELECT b.col_2 + FROM table_a b + LEFT JOIN table_e rb + ON rb.col_1 = b.col_19 + AND b.col_6 = rb.col_3 + WHERE b.col_2 = (SELECT date4 FROM date_table) +), + +rm_am_champs_ex_risk_portfolio_seed_money_2 AS ( + SELECT b.col_2 + FROM table_a b + LEFT JOIN table_e rb + ON rb.col_1 = b.col_19 + AND b.col_6 = rb.col_3 +), + +product_base AS ( + SELECT DISTINCT t.col_3, col_4, 'ML' AS is_do + FROM table_c t +), + +product_detail AS ( + SELECT t.col_4, + "3集合" AS nature_investment + FROM product_base t + LEFT JOIN date_table dt + ON 1 = 1 + LEFT JOIN table_c a + ON t.col_4 = a.col_4 + AND a.col_1 = dt.date3 +) + +SELECT col_4 + FROM ( + SELECT col_4 + FROM product_detail + UNION ALL + SELECT col_4 + FROM product_detail +) a; + +WITH date_table AS ( + SELECT + d.col_1 AS date, + (SELECT MAX(col_1) + FROM table_c a + WHERE col_1 <= + CONCAT(YEAR(DATE_SUB(d.col_1, INTERVAL 1 YEAR)), + '1231') + AND EXISTS (SELECT 1 + FROM table_d d + WHERE a.col_1 = d.col_1 + AND d.col_2 = 1)) AS date1, + (SELECT MAX(col_1) + FROM table_a a + WHERE col_1 <= CONCAT(YEAR(DATE_SUB(d.col_1, INTERVAL 1 YEAR)), + '1231') + AND EXISTS (SELECT 1 + FROM table_d d + WHERE a.col_1 = d.col_1 + AND d.col_2 = 1)) AS date2, + (SELECT MAX(col_1) + FROM table_c + WHERE col_1 <= d.col_1) AS date3, + (SELECT MAX(col_1) + FROM table_a + WHERE col_1 <= d.col_1) AS date4 + FROM table_d d + WHERE d.col_1 = '20240628' +), +rm_am_champs_ex_risk_portfolio_seed_money_1 AS ( + SELECT b.col_2 + FROM table_a b + LEFT JOIN table_e rb + ON rb.col_1 = b.col_19 + AND b.col_6 = rb.col_3 + WHERE b.col_2 = (SELECT date4 FROM date_table) +), + +rm_am_champs_ex_risk_portfolio_seed_money_2 AS ( + SELECT b.col_2 + FROM table_a b + LEFT JOIN table_e rb + ON rb.col_1 = b.col_19 + AND b.col_6 = rb.col_3 +), + +product_base AS ( + SELECT DISTINCT t.col_3, col_4, 'ML' AS is_do + FROM table_c t +), + +product_detail AS ( + SELECT t.col_4, + "3集合" AS nature_investment + FROM product_base t + LEFT JOIN date_table dt + ON 1 = 1 + LEFT JOIN table_c a + ON t.col_4 = a.col_4 + AND a.col_1 = dt.date3 +) + +SELECT col_4 + FROM ( + SELECT col_4 + FROM product_detail + UNION ALL + SELECT col_4 + FROM product_detail +) a; +>>>>>>> d04ec9d914a (planner: fix CTE hang or wrong result when multiple Apply is used (#55553)) From b38b08525b224ab100cf1edc3f364f3df0ede420 Mon Sep 17 00:00:00 2001 From: guo-shaoge Date: Tue, 24 Sep 2024 17:33:50 +0800 Subject: [PATCH 2/2] fix conflict Signed-off-by: guo-shaoge --- pkg/planner/core/rule_decorrelate.go | 12 +-- tests/integrationtest/r/cte.result | 129 +++++++++++++------------ tests/integrationtest/t/cte.test | 136 +++++++++++++-------------- 3 files changed, 133 insertions(+), 144 deletions(-) diff --git a/pkg/planner/core/rule_decorrelate.go b/pkg/planner/core/rule_decorrelate.go index 49b9543b9fbaf..6f29268dc76bb 100644 --- a/pkg/planner/core/rule_decorrelate.go +++ b/pkg/planner/core/rule_decorrelate.go @@ -128,20 +128,12 @@ func ExtractCorrelatedCols4PhysicalPlan(p PhysicalPlan) []*expression.Correlated // |_ Apply_3 // |_ outerSide // |_ innerSide(cor_col_3) -<<<<<<< HEAD func ExtractOuterApplyCorrelatedCols(p PhysicalPlan) []*expression.CorrelatedColumn { - return extractOuterApplyCorrelatedColsHelper(p, []*expression.Schema{}) -} - -func extractOuterApplyCorrelatedColsHelper(p PhysicalPlan, outerSchemas []*expression.Schema) []*expression.CorrelatedColumn { -======= -func ExtractOuterApplyCorrelatedCols(p base.PhysicalPlan) []*expression.CorrelatedColumn { corCols, _ := extractOuterApplyCorrelatedColsHelper(p) return corCols } -func extractOuterApplyCorrelatedColsHelper(p base.PhysicalPlan) ([]*expression.CorrelatedColumn, []*expression.Schema) { ->>>>>>> d04ec9d914a (planner: fix CTE hang or wrong result when multiple Apply is used (#55553)) +func extractOuterApplyCorrelatedColsHelper(p PhysicalPlan) ([]*expression.CorrelatedColumn, []*expression.Schema) { if p == nil { return nil, nil } @@ -151,7 +143,7 @@ func extractOuterApplyCorrelatedColsHelper(p base.PhysicalPlan) ([]*expression.C allCorCols := p.ExtractCorrelatedCols() allOuterSchemas := []*expression.Schema{} - handler := func(child base.PhysicalPlan) { + handler := func(child PhysicalPlan) { childCorCols, childOuterSchemas := extractOuterApplyCorrelatedColsHelper(child) allCorCols = append(allCorCols, childCorCols...) allOuterSchemas = append(allOuterSchemas, childOuterSchemas...) diff --git a/tests/integrationtest/r/cte.result b/tests/integrationtest/r/cte.result index 7e9954412c5c7..4b267e9fce11b 100644 --- a/tests/integrationtest/r/cte.result +++ b/tests/integrationtest/r/cte.result @@ -790,15 +790,6 @@ with cte1 as (select 1), cte2 as (select 2) select * from cte1 union (with cte2 1 1 3 -<<<<<<< HEAD -drop table if exists t1, t2; -create table t1(a int, b int); -create table t2(a int, b int); -insert into t1 value(5,5); -insert into t2 value(1,1); -with recursive cte1 as (select 1 as a union all select cte1.a+1 from t1 join cte1 on t1.a > cte1.a) select * from cte1; -a -======= drop table if exists tt, tt1, tt2, tt3, tt4, tt5; create table tt(c1 int, c2 int); create table tt1(c1 int, c2 int); @@ -830,66 +821,11 @@ CTE_0 8001.00 root Recursive CTE └─TableFullScan_28 100000000.00 cop[tikv] table:tt1 keep order:false, stats:pseudo with recursive cte1 as (select c1 from tt union select c1 from cte1 where exists (select /*+ no_decorrelate() */ c1 from tt1 where tt1.c2 = cte1.c1)) select c1 from tt2 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt2.c1) order by 1; c1 ->>>>>>> d04ec9d914a (planner: fix CTE hang or wrong result when multiple Apply is used (#55553)) 1 2 3 4 5 -<<<<<<< HEAD -update t2 set b=2 where a in (with recursive cte1 as (select 1 as a union all select cte1.a+1 from t1 join cte1 on t1.a > cte1.a) select * from cte1); -select * from t2; -a b -1 2 -delete from t2 where a in (with recursive cte1 as (select 1 as a union all select cte1.a+1 from t1 join cte1 on t1.a > cte1.a) select * from cte1); -select * from t2; -a b -drop table if exists table_abc1; -drop table if exists table_abc2; -drop table if exists table_abc3; -drop table if exists table_abc4; -CREATE TABLE `table_abc1` ( -`column_abc1` varchar(10) DEFAULT NULL, -`column_abc2` varchar(10) DEFAULT NULL, -`column_abc3` varchar(10) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; -CREATE TABLE `table_abc3` ( -`column_abc5` varchar(10) DEFAULT NULL, -`column_abc6` varchar(10) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; -CREATE TABLE `table_abc4` ( -`column_abc3` varchar(10) DEFAULT NULL, -`column_abc7` varchar(10) DEFAULT NULL, -`column_abc5` varchar(10) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; -INSERT INTO `table_abc1` VALUES ('KTL157','KTL157','KTL157'); -INSERT INTO `table_abc3` VALUES ('1000','20240819'); -INSERT INTO `table_abc4` VALUES ('KTL157','test','1000'); -DELETE FROM table_abc3 t_abc3 -WHERE t_abc3.column_abc5 IN ( -SELECT a.column_abc5 -FROM ( -WITH tree_cte1 AS ( -WITH RECURSIVE tree_cte AS ( -SELECT t.column_abc1, t.column_abc2, t.column_abc3, 0 AS lv -FROM table_abc1 t -WHERE t.column_abc1 IN ('KTL157', 'KTL159') -UNION ALL -SELECT t.column_abc1, t.column_abc2, t.column_abc3, tcte.lv + 1 -FROM table_abc1 t -JOIN tree_cte tcte ON t.column_abc1 = tcte.column_abc2 -WHERE tcte.lv <= 1 -) -SELECT * FROM tree_cte -) -SELECT e.column_abc5 -FROM ( -SELECT DISTINCT * FROM tree_cte1 -) aa -LEFT JOIN table_abc4 e ON e.column_abc3 = aa.column_abc3 -) a -); -======= 6 explain with recursive cte1 as (select c1 from tt union select c1 from cte1 where exists (select /*+ no_decorrelate() */ c1 from tt1 where tt1.c2 = cte1.c1)) select c1 from tt2 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt2.c1) union select c1 from tt3 where exists (select /*+ no_decorrelate() */ * from cte1 where cte1.c1 = tt3.c1) union @@ -1337,4 +1273,67 @@ FROM product_detail col_4 Product A Product A ->>>>>>> d04ec9d914a (planner: fix CTE hang or wrong result when multiple Apply is used (#55553)) +drop table if exists t1, t2; +create table t1(a int, b int); +create table t2(a int, b int); +insert into t1 value(5,5); +insert into t2 value(1,1); +with recursive cte1 as (select 1 as a union all select cte1.a+1 from t1 join cte1 on t1.a > cte1.a) select * from cte1; +a +1 +2 +3 +4 +5 +update t2 set b=2 where a in (with recursive cte1 as (select 1 as a union all select cte1.a+1 from t1 join cte1 on t1.a > cte1.a) select * from cte1); +select * from t2; +a b +1 2 +delete from t2 where a in (with recursive cte1 as (select 1 as a union all select cte1.a+1 from t1 join cte1 on t1.a > cte1.a) select * from cte1); +select * from t2; +a b +drop table if exists table_abc1; +drop table if exists table_abc2; +drop table if exists table_abc3; +drop table if exists table_abc4; +CREATE TABLE `table_abc1` ( +`column_abc1` varchar(10) DEFAULT NULL, +`column_abc2` varchar(10) DEFAULT NULL, +`column_abc3` varchar(10) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; +CREATE TABLE `table_abc3` ( +`column_abc5` varchar(10) DEFAULT NULL, +`column_abc6` varchar(10) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; +CREATE TABLE `table_abc4` ( +`column_abc3` varchar(10) DEFAULT NULL, +`column_abc7` varchar(10) DEFAULT NULL, +`column_abc5` varchar(10) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; +INSERT INTO `table_abc1` VALUES ('KTL157','KTL157','KTL157'); +INSERT INTO `table_abc3` VALUES ('1000','20240819'); +INSERT INTO `table_abc4` VALUES ('KTL157','test','1000'); +DELETE FROM table_abc3 t_abc3 +WHERE t_abc3.column_abc5 IN ( +SELECT a.column_abc5 +FROM ( +WITH tree_cte1 AS ( +WITH RECURSIVE tree_cte AS ( +SELECT t.column_abc1, t.column_abc2, t.column_abc3, 0 AS lv +FROM table_abc1 t +WHERE t.column_abc1 IN ('KTL157', 'KTL159') +UNION ALL +SELECT t.column_abc1, t.column_abc2, t.column_abc3, tcte.lv + 1 +FROM table_abc1 t +JOIN tree_cte tcte ON t.column_abc1 = tcte.column_abc2 +WHERE tcte.lv <= 1 +) +SELECT * FROM tree_cte +) +SELECT e.column_abc5 +FROM ( +SELECT DISTINCT * FROM tree_cte1 +) aa +LEFT JOIN table_abc4 e ON e.column_abc3 = aa.column_abc3 +) a +); diff --git a/tests/integrationtest/t/cte.test b/tests/integrationtest/t/cte.test index c986c31e15c41..ae9fc79d53338 100644 --- a/tests/integrationtest/t/cte.test +++ b/tests/integrationtest/t/cte.test @@ -337,74 +337,6 @@ WITH cte_0 AS (select distinct ref_0.wkey as c0, ref_0.pkey as c1, ref_0.c_xhsnd #case with cte1 as (select 1), cte2 as (select 2) select * from cte1 union (with cte2 as (select 3) select * from cte2 union all select * from cte2) order by 1; -<<<<<<< HEAD -# Tests for PR #55732 -drop table if exists t1, t2; -create table t1(a int, b int); -create table t2(a int, b int); -insert into t1 value(5,5); -insert into t2 value(1,1); -with recursive cte1 as (select 1 as a union all select cte1.a+1 from t1 join cte1 on t1.a > cte1.a) select * from cte1; -# This UPDATE should update t2.b to 2 -update t2 set b=2 where a in (with recursive cte1 as (select 1 as a union all select cte1.a+1 from t1 join cte1 on t1.a > cte1.a) select * from cte1); -select * from t2; -# This DELETE should delete all rows in t2 -delete from t2 where a in (with recursive cte1 as (select 1 as a union all select cte1.a+1 from t1 join cte1 on t1.a > cte1.a) select * from cte1); -select * from t2; - -# Issue #55666 -drop table if exists table_abc1; -drop table if exists table_abc2; -drop table if exists table_abc3; -drop table if exists table_abc4; - -CREATE TABLE `table_abc1` ( - `column_abc1` varchar(10) DEFAULT NULL, - `column_abc2` varchar(10) DEFAULT NULL, - `column_abc3` varchar(10) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; - -CREATE TABLE `table_abc3` ( - `column_abc5` varchar(10) DEFAULT NULL, - `column_abc6` varchar(10) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; - -CREATE TABLE `table_abc4` ( - `column_abc3` varchar(10) DEFAULT NULL, - `column_abc7` varchar(10) DEFAULT NULL, - `column_abc5` varchar(10) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; - -INSERT INTO `table_abc1` VALUES ('KTL157','KTL157','KTL157'); -INSERT INTO `table_abc3` VALUES ('1000','20240819'); -INSERT INTO `table_abc4` VALUES ('KTL157','test','1000'); - -DELETE FROM table_abc3 t_abc3 -WHERE t_abc3.column_abc5 IN ( - SELECT a.column_abc5 - FROM ( - WITH tree_cte1 AS ( - WITH RECURSIVE tree_cte AS ( - SELECT t.column_abc1, t.column_abc2, t.column_abc3, 0 AS lv - FROM table_abc1 t - WHERE t.column_abc1 IN ('KTL157', 'KTL159') - UNION ALL - SELECT t.column_abc1, t.column_abc2, t.column_abc3, tcte.lv + 1 - FROM table_abc1 t - JOIN tree_cte tcte ON t.column_abc1 = tcte.column_abc2 - WHERE tcte.lv <= 1 - ) - SELECT * FROM tree_cte - ) - SELECT e.column_abc5 - FROM ( - SELECT DISTINCT * FROM tree_cte1 - ) aa - LEFT JOIN table_abc4 e ON e.column_abc3 = aa.column_abc3 - ) a -); - -======= # case: test CTE with complicated Apply and other operators drop table if exists tt, tt1, tt2, tt3, tt4, tt5; create table tt(c1 int, c2 int); @@ -747,5 +679,71 @@ SELECT col_4 SELECT col_4 FROM product_detail ) a; ->>>>>>> d04ec9d914a (planner: fix CTE hang or wrong result when multiple Apply is used (#55553)) + +# Tests for PR #55732 +drop table if exists t1, t2; +create table t1(a int, b int); +create table t2(a int, b int); +insert into t1 value(5,5); +insert into t2 value(1,1); +with recursive cte1 as (select 1 as a union all select cte1.a+1 from t1 join cte1 on t1.a > cte1.a) select * from cte1; +# This UPDATE should update t2.b to 2 +update t2 set b=2 where a in (with recursive cte1 as (select 1 as a union all select cte1.a+1 from t1 join cte1 on t1.a > cte1.a) select * from cte1); +select * from t2; +# This DELETE should delete all rows in t2 +delete from t2 where a in (with recursive cte1 as (select 1 as a union all select cte1.a+1 from t1 join cte1 on t1.a > cte1.a) select * from cte1); +select * from t2; + +# Issue #55666 +drop table if exists table_abc1; +drop table if exists table_abc2; +drop table if exists table_abc3; +drop table if exists table_abc4; + +CREATE TABLE `table_abc1` ( + `column_abc1` varchar(10) DEFAULT NULL, + `column_abc2` varchar(10) DEFAULT NULL, + `column_abc3` varchar(10) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + +CREATE TABLE `table_abc3` ( + `column_abc5` varchar(10) DEFAULT NULL, + `column_abc6` varchar(10) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + +CREATE TABLE `table_abc4` ( + `column_abc3` varchar(10) DEFAULT NULL, + `column_abc7` varchar(10) DEFAULT NULL, + `column_abc5` varchar(10) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; + +INSERT INTO `table_abc1` VALUES ('KTL157','KTL157','KTL157'); +INSERT INTO `table_abc3` VALUES ('1000','20240819'); +INSERT INTO `table_abc4` VALUES ('KTL157','test','1000'); + +DELETE FROM table_abc3 t_abc3 +WHERE t_abc3.column_abc5 IN ( + SELECT a.column_abc5 + FROM ( + WITH tree_cte1 AS ( + WITH RECURSIVE tree_cte AS ( + SELECT t.column_abc1, t.column_abc2, t.column_abc3, 0 AS lv + FROM table_abc1 t + WHERE t.column_abc1 IN ('KTL157', 'KTL159') + UNION ALL + SELECT t.column_abc1, t.column_abc2, t.column_abc3, tcte.lv + 1 + FROM table_abc1 t + JOIN tree_cte tcte ON t.column_abc1 = tcte.column_abc2 + WHERE tcte.lv <= 1 + ) + SELECT * FROM tree_cte + ) + SELECT e.column_abc5 + FROM ( + SELECT DISTINCT * FROM tree_cte1 + ) aa + LEFT JOIN table_abc4 e ON e.column_abc3 = aa.column_abc3 + ) a +); +