偶尔看到sql中也有with关键字,好歹也写了几年的sql语句,居然第一次接触,无知啊。看了一位博主的文章,自己添加了一些内容,做了简单的总结,这个语句还是第一次见到,学习了。我从简单到复杂地写,希望高手们不要见笑。
AD:
今天偶尔看到sql中也有with关键字,好歹也写了几年的sql语句,居然第一次接触,无知啊。看了一位博主的文章,自己添加了一些内容,做了简单的总结,这个语句还是第一次见到,学习了。我从简单到复杂地写,希望高手们不要见笑。下面的sql语句设计到三个表,表的内容我用txt文件复制进去,这里不妨使用上一个随笔介绍的建立端到端的package的方法将这些表导入到数据库中,具体的就不说了。
简单的聚合
从orders表中选择各个年份共有共有多少客户订购了商品
第一种写法,我们可以写成这样
- selectYEAR(o.orderdate)orderyear,COUNT(distinct(custid))numCusts
- fromSales.Orderso
- groupbyYEAR(o.orderdate)
- go
要注意的是如果把group by YEAR(o.orderdata)换成group by orderyear就会出错,这里涉及到sql语句的执行顺序问题,有时间再了解一下
第二种写法,
- selectorderyear,COUNT(distinct(custid))numCusts
- from(selectYEAR(orderdate)asorderyear,custidfromsales.orders)asD
- groupbyorderyear
- go
在from语句中先得到orderyear,然后再select语句中就不会出现没有这个字段的错误了
第三种写法,
- selectorderyear,COUNT(distinct(custid))numCusts
- from(selectYEAR(orderdate),custidfromsales.orders)asD(orderyear,custid)
- groupbyorderyear
- go
在as D后面加上选择出的字段,是不是更加的清楚明了呢!
第四种写法,with出场了
- withcas(
- selectYEAR(orderdate)orderyear,custidfromsales.orders)
- selectorderyear,COUNT(distinct(custid))numCustsfromcgroupbyorderyear
- go
with可以使语句更加的经凑,下面是权威解释。
指定临时命名的结果集,这些结果集称为公用表表达式 (CTE)。该表达式源自简单查询,并且在单条 SELECT、INSERT、UPDATE、MERGE 或 DELETE 语句的执行范围内定义。该子句也可用在 CREATE VIEW 语句中,作为该语句的 SELECT 定义语句的一部分。公用表表达式可以包括对自身的引用。这种表达式称为递归公用表达式。
----MSDN
第五种写法,也可以借鉴第三种写法,这样使语句更加清楚明了,便于维护
- withc(orderyear,custid)as(
- selectYEAR(orderdate),custidfromsales.orders)
- selectorderyear,COUNT(distinct(custid))numCustsfromcgroupbyc.orderyear
- go
上面5中写法都得到相同的结果,如下图1:
图1
添加计算
现在要求要求计算出订单表中每年比上一年增加的客户数目,这个稍微复杂
- withyearcountas(
- selectYEAR(orderdate)orderyear,COUNT(distinct(custid))numCustsfromsales.ordersgroupbyYEAR(orderdate))
- selectcur.orderyearcuryear,cur.numCustscurNumCusts,prv.orderyearprvyear,prv.numCustsprvNumCusts,cur.numCusts-prv.numCustsgrowth
- fromyearcountcurleftjoinyearcountprvoncur.orderyear=prv.orderyear+1
- go
这里两次使用到with结果集。查询得到的结果如下图2
图2
复杂的计算
查找客户id,这些客户和所有来自美国的雇员至少有一笔交易记录,查询语句如下
- withTheseEmployeesas(
- selectempidfromhr.employeeswherecountry='USA'),
- CharacteristicFunctionsas(
- selectcustid,
- casewhencustidin(selectcustidfromsales.ordersasowhereo.empid=e.empid)then1else0endascharfun
- fromsales.customersasccrossjoinTheseEmployeesase)
- selectcustid,min(charfun)fromCharacteristicFunctionsgroupbycustidhavingmin(charfun)=1
- go
这里嵌套with语句,第with语句查找美国雇员的id,第二个语句使用这个结果和拥有客户的客户id和拥有关系标识做笛卡尔积运算。最后从这个笛卡尔积中通过标识找到最终的custid。
结果如下图3
图3
这里只有简单地介绍,没有深入,高手们不要见笑啊。