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;