使用with语句来写一个稍微复杂sql语句(经典,转载)

偶尔看到sql中也有with关键字,好歹也写了几年的sql语句,居然第一次接触,无知啊。看了一位博主的文章,自己添加了一些内容,做了简单的总结,这个语句还是第一次见到,学习了。我从简单到复杂地写,希望高手们不要见笑。

AD:

今天偶尔看到sql中也有with关键字,好歹也写了几年的sql语句,居然第一次接触,无知啊。看了一位博主的文章,自己添加了一些内容,做了简单的总结,这个语句还是第一次见到,学习了。我从简单到复杂地写,希望高手们不要见笑。下面的sql语句设计到三个表,表的内容我用txt文件复制进去,这里不妨使用上一个随笔介绍的建立端到端的package的方法将这些表导入到数据库中,具体的就不说了。

简单的聚合

从orders表中选择各个年份共有共有多少客户订购了商品

第一种写法,我们可以写成这样

 
  
  1. selectYEAR(o.orderdate)orderyear,COUNT(distinct(custid))numCusts
  2. fromSales.Orderso
  3. groupbyYEAR(o.orderdate)
  4. go

要注意的是如果把group by YEAR(o.orderdata)换成group by orderyear就会出错,这里涉及到sql语句的执行顺序问题,有时间再了解一下

第二种写法,

 
  
  1. selectorderyear,COUNT(distinct(custid))numCusts
  2. from(selectYEAR(orderdate)asorderyear,custidfromsales.orders)asD
  3. groupbyorderyear
  4. go

在from语句中先得到orderyear,然后再select语句中就不会出现没有这个字段的错误了

第三种写法,

 
  
  1. selectorderyear,COUNT(distinct(custid))numCusts
  2. from(selectYEAR(orderdate),custidfromsales.orders)asD(orderyear,custid)
  3. groupbyorderyear
  4. go

在as D后面加上选择出的字段,是不是更加的清楚明了呢!

第四种写法,with出场了

 
  
  1. withcas(
  2. selectYEAR(orderdate)orderyear,custidfromsales.orders)
  3. selectorderyear,COUNT(distinct(custid))numCustsfromcgroupbyorderyear
  4. go

with可以使语句更加的经凑,下面是权威解释。

指定临时命名的结果集,这些结果集称为公用表表达式 (CTE)。该表达式源自简单查询,并且在单条 SELECT、INSERT、UPDATE、MERGE 或 DELETE 语句的执行范围内定义。该子句也可用在 CREATE VIEW 语句中,作为该语句的 SELECT 定义语句的一部分。公用表表达式可以包括对自身的引用。这种表达式称为递归公用表达式。 
----MSDN

第五种写法,也可以借鉴第三种写法,这样使语句更加清楚明了,便于维护

 
  
  1. withc(orderyear,custid)as(
  2. selectYEAR(orderdate),custidfromsales.orders)
  3. selectorderyear,COUNT(distinct(custid))numCustsfromcgroupbyc.orderyear
  4. go


上面5中写法都得到相同的结果,如下图1:

图1

添加计算

现在要求要求计算出订单表中每年比上一年增加的客户数目,这个稍微复杂

 
  
  1. withyearcountas(
  2. selectYEAR(orderdate)orderyear,COUNT(distinct(custid))numCustsfromsales.ordersgroupbyYEAR(orderdate))
  3. selectcur.orderyearcuryear,cur.numCustscurNumCusts,prv.orderyearprvyear,prv.numCustsprvNumCusts,cur.numCusts-prv.numCustsgrowth
  4. fromyearcountcurleftjoinyearcountprvoncur.orderyear=prv.orderyear+1
  5. go

这里两次使用到with结果集。查询得到的结果如下图2

图2

复杂的计算

查找客户id,这些客户和所有来自美国的雇员至少有一笔交易记录,查询语句如下

 
  
  1. withTheseEmployeesas(
  2. selectempidfromhr.employeeswherecountry='USA'),
  3. CharacteristicFunctionsas(
  4. selectcustid,
  5. casewhencustidin(selectcustidfromsales.ordersasowhereo.empid=e.empid)then1else0endascharfun
  6. fromsales.customersasccrossjoinTheseEmployeesase)
  7. selectcustid,min(charfun)fromCharacteristicFunctionsgroupbycustidhavingmin(charfun)=1
  8. go

这里嵌套with语句,第with语句查找美国雇员的id,第二个语句使用这个结果和拥有客户的客户id和拥有关系标识做笛卡尔积运算。最后从这个笛卡尔积中通过标识找到最终的custid。

结果如下图3

图3

这里只有简单地介绍,没有深入,高手们不要见笑啊。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值