给定下边一张学员表student
id | name | nation | age |
---|---|---|---|
1 | 张三 | 汉族 | 40 |
2 | 李四 | 回族 | 35 |
3 | 王五 | 回族 | 37 |
4 | 赵六 | 壮族 | 28 |
如果要查询小于等于40岁的汉族学员 和 小于等于35岁的回族学员, 那么sql为:
SELECT
*
FROM
student
WHERE
( nation = '汉族' AND age <= 40 )
OR ( nation = '回族' AND age <= 35 );
而不能写作:
SELECT
*
FROM
student
WHERE
nation in ('汉族','回族')
AND (age <= 40 OR age <= 35) ;
我理解,这实际上是数学上的分类讨论思想,一定要对每种情况分别讨论,而不能混为一谈。
昨天排查一个差异配置的bug搞到半夜,问题就出在了这块的分类讨论逻辑不严谨,sql片段如下:
cdp.param_type in (0,1)
AND (
cdspi.is_custom = 1
OR (
cdspi.is_custom = 2
AND cds.is_show_general = 1
)
)
修正后的样子如下:
cdp.param_type in (0,1)
AND (
(
cdp.param_type = 1
AND cdspi.is_custom = 1
)
OR
(
cdp.param_type = 0
AND cdspi.is_custom = 2
AND cds.is_show_general = 1
)
)
on 和 where 条件的区别如下:
on 条件是在生成临时表时使用的条件
where 条件是在临时表生成好后,再对临时表进行过滤的条件
tab1
id | size |
---|---|
1 | 10 |
2 | 20 |
3 | 30 |
tab2
size | name |
---|---|
10 | AAA |
20 | BBB |
20 | CCC |
分析两条sql:
select * from tab1
left join tab2 on (tab1.size = tab2.size)
where tab2.name='AAA'
select * from tab1
left join tab2
on (tab1.size = tab2.size and tab2.name='AAA')
前者的执行过程是先生成了一张如下的临时表:
tab1.id | tab1.size | tab2.size | tab2.name |
---|---|---|---|
1 | 10 | 10 | AAA |
2 | 20 | 20 | BBB |
2 | 20 | 20 | CCC |
3 | 30 | null | null |
然后再用tab2.name='AAA’过滤,最终只得到第一条数据
后者的执行过程是先生成只有一条数据的临时表,然后跟左表进行左关联,得到如下结果
tab1.id | tab1.size | tab2.size | tab2.name |
---|---|---|---|
1 | 10 | 10 | AAA |
2 | 20 | null | null |
3 | 30 | null | null |