一种生成自然数列的方式
--创建一个包含0-9整数的
create table natural_num(sn int);
insert into natural_num values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)
然后我们使用下面这种方式生成一个包含0-999自然数的数据集:
create table num_test as
select tab1*1+tab2*10+tab3*100 from
natural_num tab1,
natural_num tab2,
natural_num tab3;
--这里natural_num进行自连接, 可以将这三个表看成不同的名称的表,只是其内容完全一样
同时以上数的生成方式, 隐藏着一个惊天的大秘密, 那就是, 关系(数据库中的表)中的一条条数据是没有顺序的。
上述SQL中自然数生成的原理:tab1*1 包含了0-9 这10个数, 分别与tab2*10,比如1*10相加会得到10-19, 这十个数, 2*10相加会得到20-29 十个数, 10个数全部进行这样的操作, 会得到0-99共100个数。
如果在加入一个百位,则会得到0-999共1000个数。
我表述得不是很清楚,看看下面这个图吧:
一般情况下连续自然数的定义方式是:(int i=1;i<=100;i++), 类似于递归的一种方式产生。但是这里我们生成的方式完全是采用了面向集合的思想。仔细想一想还是挺有意思的。
这个东西有没有用呢?还是有点儿用的,之前同事bigquerry通过循环往表里面插入数据, 结果公司bigquerry有表update次数限制,不可插入1000次,于是我就用这个给搞定了。
连续坐位问题
假设我要和我的两个女朋友去电影院看电影, 然后我们三个要坐在一起, 电影院老板告诉了了我还剩哪些位置。 那么entity来了,我和我的女朋友们, 有哪些位置选择呢?
首先我们来把模型简化一下,所有的座位都在一排。
首先通过自连接, 获取所有间隔一个位置的坐位(可以坐三个人)的组合:
select * from seats st1, seats st2 where st1 = st2-2;
这样就得到了所有的坐位号码的两两组合(假设我有10个坐位):
1 3
2 4
3 5
4 6
5 7
···
8 10
然后我需要检查这些编号之间的坐位的情况, 怎么检查呢?子查询:
select * from seats st1, seats st2
where st1 = st2-2
and not exist (select * from seats st3
where st3 between st1 and st2
and status <> empty);
这里有三个关键点需要解释
- exists 谓词(所谓谓词,就是一个返回值为boolean类型的函数);exists 谓词传入的参数只要不为空,即返回true;这个谓词是比较神奇的, 可以看看我前面写的关于谓词的内容。
- 全称量化;也就是我们经常说的: “在座的各位全部都是垃圾”。但是在sql中我们没有这么不礼貌的话(ALL 这个谓词没给安排上),我们使用“没有一个不是垃圾”, 即“不存在 不是 ”, not exist !=。这个相信我们在小学数学里面就学过的:一个名题的逆反命题等于他本身。
- 子查询。外部查询会把结果一条条传入内部查询进行比较, 内部查询完成后将结果返回外部查询。你自己去了解下。
到这里,我们就解决了一长排坐位我和女友们选座的问题。
多排的情况
电影院是不可能搞这么一个长排的。真实情况下,我怎么选呢?愁死我了。
经过思考我发下: 座位号(假设100个坐位号编号为1-100, 而不是只是1-10, 11-20 这种10个一排的尘世间的情形),除以每排的坐位数,如果商一样他们就在一排,如果模一样, 他们就在一列。
所以我们加一个条件: where st1/10=st2/10,问题就解决了。