0、逻辑查询的各个阶段 执行顺序
T-SQL逻辑查询的各个阶段(编号代表顺序)
(5)SELECT DISTINCT TOP(<top_specification>) <select_list>
(1)FROM <left_table> <join_type> JOIN <right_table> ON <on_predicate>
(2)WHERE <where_predicate>
(3)GROUP BY <group_by_specification>
(4)HAVING <having_predicate>
(6)ORDER BY <order_by_list>
T-SQL在查询各个阶级分别干了什么:
(1)FROM 阶段
FROM阶段标识出查询的来源表,并处理表运算符。在涉及到联接运算的查询中(各种join),主要有以下几个步骤:
a.求笛卡尔积。不论是什么类型的联接运算,首先都是执行交叉连接(cross join),求笛卡儿积,生成虚拟表VT1-J1。
b.ON筛选器。这个阶段对上个步骤生成的VT1-J1进行筛选,根据ON子句中出现的谓词进行筛选,让谓词取值为true的行通过了考验,插入到VT1-J2。
c.添加外部行。如果指定了outer join,还需要将VT1-J2中没有找到匹配的行,作为外部行添加到VT1-J2中,生成VT1-J3。
经过以上步骤,FROM阶段就完成了。概括地讲,FROM阶段就是进行预处理的,根据提供的运算符对语句中提到的各个表进行处理(除了join,还有apply,pivot,unpivot)
(2)WHERE阶段
WHERE阶段是根据<where_predicate>中条件对VT1中的行进行筛选,让条件成立的行才会插入到VT2中。
(3)GROUP BY阶段
GROUP阶段按照指定的列名列表,将VT2中的行进行分组,生成VT3。最后每个分组只有一行。
(4)HAVING阶段
该阶段根据HAVING子句中出现的谓词对VT3的分组进行筛选,并将符合条件的组插入到VT4中。
(5)SELECT阶段
这个阶段是投影的过程,处理SELECT子句提到的元素,产生VT5。这个步骤一般按下列顺序进行
a.计算SELECT列表中的表达式,生成VT5-1。
b.若有DISTINCT,则删除VT5-1中的重复行,生成VT5-2
c.若有TOP,则根据ORDER BY子句定义的逻辑顺序,从VT5-2中选择签名指定数量或者百分比的行,生成VT5-3
(6)ORDER BY阶段
根据ORDER BY子句中指定的列明列表,对VT5-3中的行,进行排序,生成游标VC6.
如果是inner join, 放on和放where产生的结果一样, 执行计划也是一样,但推荐使用on。但如果有outer join (left or right), 就有区别了, 因为on生效在先, 已经提前过滤了一部分数据, 而where生效在后,而且on对于outer join有不生效的情况,需要看and条件是作用在左表还是右表。
1、oracle数据库的decode函数
--O:这个函数运行的结果是,当X = A,函数返回B;当X != A 且 X = C,函数返回D;当X != A 且 X != C,函数返回E。 其中,X、A、B、C、D、E都可以是表达式。
decode(X,A,B,C,D,E)
--S:有两种等价方式
CASE X WHEN A THEN B WHEN C THEN D ELSE E END
CASE WHEN X=A THEN B WHEN X = C THEN D ELSE E END
2、oracle中的||
--O:‘ABC’||‘EFG’ result=> ABCEFG
‘ABC’||‘EFG’
--S:可以视作spark sql中的concat函数
concat(‘ABC’, ‘EFG’)
3、oracle中的wm_concat()
--O:oracle中的wm_concat() 独有的,mysql中有一个group_concat()函数
--实现行转列功能,即将查询出的某一列值使用逗号进行隔开拼接,成为一条数据
select to_char(wm_concat(column))
--S:可以视作spark sql中的
select concat_ws(',',collect_set(column))
4、oracle 中的 trunc
--S:date_format将时间转化为某种格式的字符串
select date_format('2016-04-08', 'y')
5、spark sql 日期时间转换
SELECT unix_timestamp('2016-04-08', 'yyyy-MM-dd')
SELECT to_unix_timestamp('2016-04-08', 'yyyy-MM-dd')
SELECT to_date('2009-07-30 04:17:52')
--quarter 将1年4等分(range 1 to 4)
SELECT quarter('2016-08-31')
--months_between两个日期之间的月数
SELECT months_between('1997-02-28 10:30:00', '1996-10-30')
--datediff 两个日期间的天数
SELECT datediff('2009-07-31', '2009-07-30')
--add_months返回日期后n个月后的日期
SELECT add_months('2016-08-31', 1)
--last_day(date),next_day(start_date, day_of_week)
SELECT last_day('2009-01-12') --2009-01-31
SELECT next_day('2015-01-14', 'TU') --2015-01-20
--date_add,date_sub(减)
SELECT date_add('2016-07-30', 1) --2016-07-31
6、Oracle中 replace
--O:Oracle中 replace
select replace(name,' ')
--S:
select regexp_replace(name,'正则匹配','要替换的数据')
7、oracle中的(+)
--oracle中的(+)是一种特殊的用法,(+)表示外连接,并且总是放在非主表的一方。有 (+) 的一方代表有可以为空,即副表。
--左外连接
select A.a,B.a from A LEFT JOIN B ON A.b=B.b;
--等价于
select A.a,B.a from A,B where A.b = B.b(+);
--右外连接
select A.a,B.a from A RIGHT JOIN B ON A.b=B.b;
--等价于
select A.a,B.a from A,B where A.b (+) = B.b;
--内连接(自然连接): 只有两个表相匹配的行才能在结果集中出现
--外连接:
--左外连接(左边的表不加限制)
--右外连接(右边的表不加限制)
--全外连接(左右两表都不加限制)
--自连接:
--(连接发生在一张基表内)
8、oracle 批量插入数据
INSERT ALL
INTO my_table(field_1,field_2) VALUES (value_1,value_2)
INTO my_table(field_1,field_2) VALUES (value_3,value_4)
INTO my_table2(field_3,field_4) VALUES (value_5,value_6)
SELECT 1 FROM DUAL;