无论是数仓开发还是数据分析,写一手好的SQL是一项根本的技能。毋庸置疑,编写性能较好的SQL是十分重要的,然而,SQL的可读性同样是不容小觑的。一个有着凌乱格局的SQL脚本,往往须要破费较长的工夫去弄清楚脚本的具体逻辑。如果你已经被祖传的毫无章法的SQL脚本狂虐过,你肯定心有感触。本文将分享几个SQL格局的标准,当然仁者见仁智者见智,其实没有严格的规范,如果有,那就是保障易于浏览和易于保护。
秦人不暇自哀,而后人哀之;前人哀之而不鉴之,亦使前人而复哀前人也
大小写保持一致
能够对SQL关键字应用不同的大小写,然而要保持一致。看看这个:
SELECT customer_city,count(*) from dim_customer WHERE customerProvince = '上海' Group by customer_city
下面的SQL语句是不是很让人抓狂,大小写混用,看起来很不标准。总结起来,要留神上面几点:
- SQL的关键字能够大写,也能够小写,然而不要大小写混用。下面的SQL查问既有齐全大写,也有首字母大写,更有小写。看似是不拘小节,然而万万使不得。
- 因为大小写是混合的,因而很难辨别小写的关键字实际上是关键字还是列。此外,浏览也很烦人。
- 字段命名要保持一致的格调,下面的SQL与中
customer_city
是小写加下划线,而customerProvince
字段是驼峰命名法,这种不一致性显然是不可取的。
进行一些标准之后后,查问应如下所示:
SELECT customer_city, count(*)FROM dim_customerWHERE customer_province = '上海'GROUP BY customer_city
应用缩进
再来看看上面的一条查问语句:
SELECT dp.region_name,count(*) FROM user_behavior_log ubl JOIN dim_province dp ON ubl.province = dp.province_name WHERE ubl.province = '上海市' GROUP BY dp.region_name
将下面的SQL语句格式化上面的模式:
SELECT dp.region_name, count(*)FROM user_behavior_log ublJOIN dim_province dp ON ubl.province = dp.province_nameWHERE ubl.province = '上海市'GROUP BY dp.region_name
下面的格式化模式仿佛清晰了很多,然而如果语句中蕴含了子查问、多个JOIN以及窗口函数时,同样会显得对浏览不是很敌对。
再换一种格式化形式,如下:
SELECT dp.region_name, count(*)FROM user_behavior_log ubl JOIN dim_province dp ON ubl.province = dp.province_nameWHERE ubl.province = '上海市'GROUP BY dp.region_name-- 或者上面的模式SELECT dp.region_name ,count(*)FROM user_behavior_log ubl JOIN dim_province dp ON ubl.province = dp.province_nameWHERE ubl.province = '上海市'GROUP BY dp.region_name
尖叫提醒:对于第二种模式,在SELECT字段中,从第二个字段开始,每个字段后面增加一个逗号,而不是每个字段前面应用逗号结尾。这种形式能够很不便地辨认FROM后面是否存在逗号,从而造成语法错误。当然,这个只是集体习惯问题,并不是硬性的规定。另外下面的SQL语句应用了4个字符缩进,当然也能够抉择2个字符缩进,这个也是集体习惯问题。
在group by 和order by之后应用字段的排列序号
同样,这种书写格调也是集体的一种偏好,并不是一条硬性规定。应该有很多的初学者对此种写法并不是很分明。
看上面的这条SQL:
SELECT dp.region_name, dp.province_name, count(*)FROM user_behavior_log ubl JOIN dim_province dp ON ubl.province = dp.province_nameGROUP BY dp.region_name, dp.province_nameORDER BY count(*) desc -- Hive不反对
能够写成上面的模式:
-- 留神:MySQL、Impala反对这种写法,Hive不反对SELECT dp.region_name, dp.province_name, count(*)FROM user_behavior_log ubl JOIN dim_province dp ON ubl.province = dp.province_nameGROUP BY 1,2ORDER BY 3
这样写有如下的益处:
- 能够节俭行:通过许多字段进行分组不仅会在SELECT子句中增加更多行,还会在GROUP BY和ORDER BY子句中增加更多行,甚至可能使查问中的行数增加一倍。
- 可维护性:如果想扭转分组字段,只需在SELECT子句中进行操作,在GROUP BY语句中不须要批改。
- 不便:只须要GROUP BY 1,2,3,…,n,其中n为分组列的字段序号。
应用Common Table表达式(with语句)
该形式称之为Common Table Expressions(CTE),用来简化简单查问。它们能够定义为长期视图,因为它们仅在整个查问执行期间存在。
看一个简略的例子:
-- 留神Hive、Impala反对这种语法,低版本的MySQL不反对(高版本反对)WITH employee_by_title_count AS ( SELECT t.name as job_title , COUNT(e.id) as amount_of_employees FROM employees e JOIN job_titles t on e.job_title_id = t.id GROUP BY 1),salaries_by_title AS ( SELECT name as job_title , salary FROM job_titles)SELECT *FROM employee_by_title_count e JOIN salaries_by_title s ON s.job_title = e.job_title
下面的语句中,最终的查问应用employee_by_title
和salaries_by_title
的两个后果集进行JOIN产生最终后果。这比在SELECT子句中或间接在FROM子句中进行子查问更具可读性和可维护性。
应用具备描述性的别名
这一点十分重要,如果查问的列字段很多,肯能会存在一些id,count(*)等,很难辨识代表什么含意,所以须要为每个查问列加上可读的、易于了解的别名,可能让其他人一眼就能看出代表什么含意,这样能够减少脚本的可维护性。
总结
文中提到的一些标准有些是必须要恪守的,有些是集体的编码习惯,无论你是开发人员、数据分析师、数仓开发,遵循一些标准能够防止不必要的麻烦。值得注意的是,对于SQL的格局,没有一个规范的约定,须要与团队的其余成员达成共识,一起依照雷同的约定进行开发,从而能够大大提高脚本的可读性和可维护性。
公众号『大数据技术与数仓』,回复『材料』支付大数据资料包