SQL中的WITH语句:公共表达式CTE,用作临时视图或子查询的定义方式,创建临时的结果集
在SQL中,WITH语句通常被用作一种临时视图或子查询的定义方式,可以创建临时的结果集,这些结果集可以在主查询中被引用。这种结构也被称为公共表达式(CTE:Common Table Expressions)。
WITH tmp_name AS (SELECT column1, column2, ...FROM table_nameWHERE condition)SELECT ...FROM tmp_nameWHERE condition;
这里通过表data_learning.product_order(商品销量表)、data_learning.product(商品信息表)、data_learning.product_category(商品二级分类信息表)进行举例,data_learning是之前创建的数据库。数据表示例数据分别如下:
data_learning.product_order(商品销量表):

data_learning.product(商品信息表):

data_learning.product_category(商品二级分类信息表):

具体的创建数据库和数据表的SQL语句可以查看我之前的文章。
SQL创建数据库和数据表
数据分析师的日常,公众号:数据分析师的日常SQL创建数据库和数据表
通过WITH语句,我们可以封装复杂的子查询或视图,使其可重用。这样可以提高查询的可读性和可维护性。例如,假设我们需要在多个查询中使用某个常用的逻辑操作。使用WITH语句,我们可以将该逻辑操作封装为一个临时表,并在需要的地方重复使用。
比如
问题:查询商品数量超过5的商品类别,常见的SQL如下:
SELECTb.category_name,COUNT(DISTINCT a.product_id) as product_cntFROMdata_learning.product_order aLEFT JOINdata_learning.product_category bON a.category_id = b.category_idGROUP BY 1HAVING COUNT(DISTINCT a.product_id) > 5ORDER BY 2 DESC;
使用with语句可以转换为:
with tmp as(SELECTb.category_name,COUNT(DISTINCT a.product_id) as product_cntFROMdata_learning.product_order aLEFT JOINdata_learning.product_category bON a.category_id = b.category_idGROUP BY 1)SELECTcategory_name,product_cntFROMtmpWHERE product_cnt > 5ORDER BY 2 DESC;
在实际工作中,在涉及到要使用多个表的多个业务时间字段时,我会先使用with语句建一个临时结果集,再写其他查询语句。当然,有建表权限的话可以直接建一个临时表,再做查询。
复杂的业务逻辑可能需要多个步骤来计算最终结果。使用WITH语句可以使这些步骤更清晰。问题:查询销量超过2000的商品类别,这个类别有哪些产品及对应的产品价格和销量时多少。
with tmp1 as(-- 首先找出销量超过2000的商品类别SELECTcategory_id,sales_volumeFROMdata_learning.product_orderWHEREsales_volume > 2000),tmp2 as (-- 接着找出属于这些商品类别的产品名称及价格、销量SELECTa.category_id,a.product_id,a.sales_volume,b.product_name,b.priceFROMdata_learning.product_order aLEFT JOINdata_learning.product bON a.product_id = b.product_idWHEREa.category_id IN (SELECT category_id FROM tmp1))-- 从最终的表中选择结果SELECT*FROMtmp2;
实际工作中涉及到的情况比这个步骤可能更多,此示例仅供理解WITH语句在分解多业务步骤逻辑中的应用。
WITH语句也可以用来进行数据清洗,例如以下查询将删除重复的数据。
以下SQL语句仅供理解使用。
WITH CTE AS(SELECT*,ROW_NUMBER() OVER (PARTITION BY duplicate_column ORDER BY duplicate_column) AS row_numFROM your_table)DELETE FROM CTEWHERE row_num > 1;
WITH语句在数据分析中非常有用,上述仅仅举了几个我在实际工作中比较常用的一些应用场景,实际上其应用场景远不止这些,也欢迎朋友们一起交流自己在实际工作中都如何使用WITH语句。