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、当年 正常月份,季度,年 日期展示,Special 处理的 季度和年(rollback)展示
1) -- 涉及 Hive 函数
substr(string,1,7) => 字符串截图函数
add_months(date|string|timestamp,int_number_month) => 传入正负月份数量,return : 几月前几月后日期 (根据传入月份参数,获取数月前/ 数月后 日期函数)
date_sub(current_timestamp(),1) => (根据传入数量 ,获取 数天前/数天后 的日期函数)
date_format(date|string|timestamp,'yyyy-MM') => 日期格式化函数
综合应用 => add_months(date_sub(current_timestamp(),1),-1)
当前时间【前一天】上个月的月份信息 :当前 2020-02-02 return 2020-01-02
2) -- 涉及 实现 算法
Special Season/Year
① Table_Month%3=0 or date_format(Table_Date_Str,'yyyy-MM')=substr(add_months(date_sub(current_timestamp(),1),-1),1,7) 季
② Table_Year%12=0 or date_format(Table_Date_Str,'yyyy-MM')=substr(add_months(date_sub(current_timestamp(),1),-1),1,7) 年
3) -- 从 日期码表 中 以上算法 所需的字典表
select
year_month_str, -- 202102
season_str, --2021Q1
year_str, --2021
case when ① then t1.season_str end special_season,
case when ② then t1.year_str end endspecial_year
from dual_zl_date_code t1
-- 以下是获取 一定时间范围内的数据 date_str => 2021-02-27 12:12:12
where t1.date_str >= add_months(date_sub(current_timestamp(),1),-24)
and t1.date_str <= add_months(date_sub(current_timestamp(),1),-1);
字典表 - 实现逻辑:
当前 月,季度,年,取当前的对应数据即可 ;
Special Season : 赋值上月 给【季度日期】属性,当月为空
Special Year : 赋值上月 给【年日期】属性,当月为空
2、计算日期之间相差的月份 函数
-- 两个日期之间的 月数差,存在小数
months_between(date|string|timestamp date1,date|string|timestamp date2)
3、针对浮点数取整函数
floor(Double a) -- 向下取整函数
ceil(Double a) -- 向上取整函数
round(Double a) -- 四舍五入 取整函数
4、区间判断函数
case when condition1 then value1 else value2 end
5、行转列,列转行
行转列可以使用collect_list() (不去重)和collect_set() (去重)
列转行可以使用explode(),但是exploade()有一定使用限制,所以一般配合lateral view 一起使用