关于数据仓库:数仓规范使SQL更易于阅读的几个小技巧

31次阅读

共计 3027 个字符,预计需要花费 8 分钟才能阅读完成。

无论是数仓开发还是数据分析,写一手好的 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_customer
WHERE 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 ubl
JOIN dim_province dp ON ubl.province = dp.province_name
WHERE 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_name
WHERE 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_name
WHERE 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_name
GROUP BY
    dp.region_name,
    dp.province_name
ORDER 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_name
GROUP BY 1,2
ORDER 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_titlesalaries_by_title的两个后果集进行 JOIN 产生最终后果。这比在 SELECT 子句中或间接在 FROM 子句中进行子查问更具可读性和可维护性。

应用具备描述性的别名

这一点十分重要,如果查问的列字段很多,肯能会存在一些 id,count(*)等,很难辨识代表什么含意,所以须要为每个查问列加上可读的、易于了解的别名,可能让其他人一眼就能看出代表什么含意,这样能够减少脚本的可维护性。

总结

文中提到的一些标准有些是必须要恪守的,有些是集体的编码习惯,无论你是开发人员、数据分析师、数仓开发,遵循一些标准能够防止不必要的麻烦。值得注意的是,对于 SQL 的格局,没有一个规范的约定,须要与团队的其余成员达成共识,一起依照雷同的约定进行开发,从而能够大大提高脚本的可读性和可维护性。

公众号『大数据技术与数仓』,回复『材料』支付大数据资料包

正文完
 0