expected result: 0, NULL, 3
Additionally, we can see from the query plan that the optimizer select a inner join algorithm (CARTESIAN inner join) for left join evaluation.
Projection_13,10000.00,root,"","database15.t0.c0, Column#5, database15.t3.c0"
└─HashJoin_15,10000.00,root,"","CARTESIAN inner join, other cond:lt(and(case(eq(1, cast(Column#5, double BINARY)), database15.t3.c0, NULL), database15.t0.c0), 1)"
├─HashJoin_16(Build),1.00,root,"",CARTESIAN inner join
│ ├─TableReader_21(Build),1.00,root,"",data:TableFullScan_20
│ │ └─TableFullScan_20,1.00,cop[tikv],table:t3,"keep order:false, stats:pseudo"
│ └─TableReader_19(Probe),1.00,root,"",data:TableFullScan_18
│ └─TableFullScan_18,1.00,cop[tikv],table:t0,"keep order:false, stats:pseudo"
└─Projection_22(Probe),10000.00,root,"",<nil>->Column#5
└─TableReader_24,10000.00,root,"",data:TableFullScan_23
└─TableFullScan_23,10000.00,cop[tikv],table:t2,"keep order:false, stats:pseudo"
Release Version: v9.0.0-beta.1.pre-801-gd7d62ce0d2
Edition: Community
Git Commit Hash: d7d62ce0d26d15b902361010aab2526a4e2c511f
Git Branch: HEAD
UTC Build Time: 2025-05-25 04:45:44
GoVersion: go1.23.9
Race Enabled: false
Check Table Before Drop: false
Store: tikv
Bug Report
Dear Developers,
I meet some unexpected result, and I analyze the root case. The optimizer wrongly choose inner join when handling left join in this query.
1. Minimal reproduce step (Required)
2. What did you expect to see? (Required)
3. What did you see instead (Required)
Additionally, we can see from the query plan that the optimizer select a inner join algorithm (CARTESIAN inner join) for left join evaluation.
4. What is your TiDB version? (Required)