笛卡尔积|SQL查询中笛卡尔积的巧妙使用( 二 )

笛卡尔积|SQL查询中笛卡尔积的巧妙使用



通过手动构造dt和dhour,用笛卡尔积产生了一个“序列” 。而对于dhour的构造,也可以采用笛卡尔积的方式,但需要注意限制范围不大于23,代码如下:
with t_hour as (select '0' as idunion all select '1' as idunion all select '2' as id ),f_hour as (select '0' as idunion all select '1' as idunion all select '2' as idunion all select '3' as idunion all select '4' as idunion all select '5' as idunion all select '6' as idunion all select '7' as idunion all select '8' as idunion all select '9' as id)select concat(a.id, b.id) hourfrom t_hour a, f_hour bwhere concat(a.id, b.id) <= '23'order by hour以上我们都主要使用了笛卡尔积产生顺序值的场景,类似的可以构造从00~99的数字,构造之后也可以根据实际需要加入新的限制条件 。
例子2-模拟循环:遍历字符串,每行按顺序输出一个字符注:例子来源于《SQL Cookbook》第6章,经过自己的修改 。
问题:考虑用SQL实现:将表emp中name为KING的字符串显示为4行,每行包含其中一个字符 。
这里需要笛卡尔积配合字符串截取函数来实现 。要实现逐一访问字符串,需要有一个中间表,存储序列值,百思特网类似于前面提到的序列 。我们看下下面的代码:
with t5 as (select 1 as posunion all select 2 as pos union allselect 3 as pos union allselect 4 as pos union allselect 5 as pos ),emp as (select 'KING' as name)select *from emp, t5得到的结果如下图所示:
笛卡尔积|SQL查询中笛卡尔积的巧妙使用



考虑到字符串截取函数能够按位置截取 。正好可以用上生成的pos 。代码如下:
with t5 as (select 1 as posunion all select 2 as pos union allselect 3 as pos union allselect 4 as pos union allselect 5 as pos ),emp as (select 'KING' as name)select substr(name, pos, 1)from emp, t5where t5.pos <= length(emp.name)

【笛卡尔积|SQL查询中笛卡尔积的巧妙使用】

笛卡尔积|SQL查询中笛卡尔积的巧妙使用



可以看到使用了pos,就能够“循环”地截取字符串了 。需要注意where里加上了循环跳出的条件,这也比较好理解:不能截取超过字符串长度的字符 。
还可以按照需要调整遍历时输出的格式,如下面代码和结果所示:
select substr(name, pos) char_name1,substr(name, length(name)-pos+1) char_name1from emp, t5where t5.pos <= length(emp.name)笛卡尔积|SQL查询中笛卡尔积的巧妙使用



这个例子中我们利用笛卡尔积模拟循环,对字符串进行了遍历 。
小结本文首先学习了with as的用法,然后通过例子总结了两个巧妙使用笛卡尔积的场景:生成序列和模拟循环 。虽然在实际中可能用的不是很多,但也体现出了SQL的灵活性 。生成序列可以更广义的理解为:需要产生两个表中字段的任意组合,这两个字段可能是没有实际联系的 。可以参考下面链接中关于每个班级血型的例子,核心思想也是这个 。
https://blog.csdn.net/xiaolinyouni/article/details/6943337
实际中应该有很多类似的场景 。
而模拟循环是笛卡尔积结合了字符串截取函数实现的,本质上还是“组合” 。下次再遇到类似场景的时候,可以考虑下笛卡尔积能否实现 。
除此以外《SQL Cookbook》中也百思特网提到了笛卡尔积可以用于结果转置~有机会我们以后再来学习 。本文代码不是很复杂,后台回复“笛卡尔积”可以获取本文pdf版本,便于阅读保存 。