一种生成自然数列的方式



--创建一个包含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个数。

我表述得不是很清楚,看看下面这个图吧:




SQL SERVER 结果相加 sql数字相加_子查询


一般情况下连续自然数的定义方式是:(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);


这里有三个关键点需要解释

  1. exists 谓词(所谓谓词,就是一个返回值为boolean类型的函数);exists 谓词传入的参数只要不为空,即返回true;这个谓词是比较神奇的, 可以看看我前面写的关于谓词的内容。
  2. 全称量化;也就是我们经常说的: “在座的各位全部都是垃圾”。但是在sql中我们没有这么不礼貌的话(ALL 这个谓词没给安排上),我们使用“没有一个不是垃圾”, 即“不存在 不是 ”, not exist !=。这个相信我们在小学数学里面就学过的:一个名题的逆反命题等于他本身。
  3. 子查询。外部查询会把结果一条条传入内部查询进行比较, 内部查询完成后将结果返回外部查询。你自己去了解下。

到这里,我们就解决了一长排坐位我和女友们选座的问题。

多排的情况

电影院是不可能搞这么一个长排的。真实情况下,我怎么选呢?愁死我了。

经过思考我发下: 座位号(假设100个坐位号编号为1-100, 而不是只是1-10, 11-20 这种10个一排的尘世间的情形),除以每排的坐位数,如果一样他们就在一排,如果一样, 他们就在一列。

所以我们加一个条件: where st1/10=st2/10,问题就解决了。