• SQL点滴9—使用with语句来写一个稍微复杂sql语句


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

    从这里下载文件employees.txt,customers.txt,orders.txt

    参考文章:http://www.cnblogs.com/wwan/archive/2011/02/24/1964279.html

    使用package导入数据:http://www.cnblogs.com/tylerdonet/archive/2011/04/17/2017471.html

    简单的聚合

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

    •  第一种写法,我们可以写成这样
      1select YEAR(o.orderdate) orderyear,COUNT(distinct(custid)) numCusts
      2from Sales.Orders o
      3group by YEAR(o.orderdate)
      4go
      要注意的是如果把group by YEAR(o.orderdata)换成group by orderyear就会出错,这里涉及到sql语句的执行顺序问题,有时间再了解一下          
    • 第二种写法,
      1select orderyear,COUNT(distinct(custid))numCusts
      2from (select YEAR(orderdate) as orderyear,custid from sales.orders) as D
      3group by orderyear
      4go
      在from语句中先得到orderyear,然后再select语句中就不会出现没有这个字段的错误了
    • 第三种写法,
      1select orderyear,COUNT(distinct(custid)) numCusts
      2from (select YEAR(orderdate),custid from sales.orders) as D(orderyear,custid)
      3group by orderyear
      4go
      在as D后面加上选择出的字段,是不是更加的清楚明了呢!
    • 第四种写法,with出场了
      1with c as(
      2select YEAR(orderdate) orderyear, custid from sales.orders)
      3select orderyear,COUNT(distinct(custid)) numCusts from c group by orderyear
      4go
      with可以使语句更加的经凑,下面是权威解释。  
          
      指定临时命名的结果集,这些结果集称为公用表表达式 (CTE)。该表达式源自简单查询,并且在单条 SELECT、INSERT、UPDATE、MERGE 或 DELETE 语句的执行范围内定义。该子句也可用在 CREATE VIEW 语句中,作为该语句的 SELECT 定义语句的一部分。公用表表达式可以包括对自身的引用。这种表达式称为递归公用表表达式。               

                                                            ----MSDN

    • 第五种写法,也可以借鉴第三种写法,这样使语句更加清楚明了,便于维护
      1 with c(orderyear,custid) as(
      2  select YEAR(orderdate),custid from sales.orders)
      3  select orderyear,COUNT(distinct(custid)) numCusts from c group by c.orderyear
      4  go
      上面5中写法都得到相同的结果,如下图1:图1
        

    添加计算

    • 现在要求要求计算出订单表中每年比上一年增加的客户数目,这个稍微复杂
      1 with yearcount as(
      2 select YEAR(orderdate) orderyear,COUNT(distinct(custid)) numCusts from sales.orders group by YEAR(orderdate))
      3 select cur.orderyear curyear,cur.numCusts curNumCusts,prv.orderyear prvyear,prv.numCusts prvNumCusts,cur.numCusts-prv.numCusts growth
      4 from yearcount cur left join yearcount prv on cur.orderyear=prv.orderyear+1
      5 go
      这里两次使用到with结果集。查询得到的结果如下图2

      图2

    复杂的计算

    • 查找所有美国雇员掌握的所有至少有一个订单的客户的客户id,查询语句如下
      1 with TheseEmployees as(
      2 select empid from hr.employees where country='USA'),
      3 CharacteristicFunctions as(
      4 select custid,
      5 case when custid in (select custid from sales.orders as o where o.empid=e.empid) then 1 else 0 end as charfun
      6 from sales.customers as c cross join TheseEmployees as e)
      7 select custid,min(charfun) from CharacteristicFunctions group by custid having min(charfun)=1
      8 go
      这里嵌套with语句,第with语句查找美国雇员的id,第二个语句使用这个结果和拥有客户的客户id和拥有关系标识做笛卡尔积运算。最后从这个笛卡尔积中通过标识找到最终的custid。
      结果如下图3

      图3

    引用至: http://www.cnblogs.com/tylerdonet/archive/2011/04/18/2020225.html


    CREATE TABLE #tempTotalCBM
    ( Appointid int,
      TotalCBM NUMERIC
    )

    INSERT INTO #tempTotalCBM (Appointid,TotalCBM)
    SELECT H.APPOINTID,
    CAST(( CASE H.TruckerConfirm WHEN 'D' THEN SUM(D.DELIVERYCBM) ELSE SUM(D.CBM) END ) AS NUMERIC) AS TotalCBM
    FROM
    (
        SELECT APPOINTID , TruckerConfirm
        FROM CCC_TAHEADER
        WHERE
        DATEDIFF(D,RECEIVEDATE,'2010-10-01') <= 0
        AND DATEDIFF(D,RECEIVEDATE,GETDATE()) >= 0
    ) H
    INNER JOIN CCC_TADETAIL D
    ON D.APPOINTID = H.APPOINTID
    GROUP BY H.APPOINTID,H.TruckerConfirm

    SELECT M.APPOINTID,M.LOADTYPE,N.TotalCBM,
     L_TruckSize3T, L_TruckSize5T, L_TruckSize8T, L_TruckSize10T, L_TruckSize12T,
     Size20, Size40, Size40R, Size40HQ, Size45,ReceiveDate
    FROM CCC_TAHEADER M
    INNER JOIN
    #tempTotalCBM N
    ON M.APPOINTID = N.Appointid

    -- SELECT * FROM #tempTotalCBM
    DROP TABLE #tempTotalCBM







    with c as (
    SELECT H.APPOINTID,
    CAST(( CASE H.TruckerConfirm WHEN 'D' THEN SUM(D.DELIVERYCBM) ELSE SUM(D.CBM) END ) AS NUMERIC) AS TotalCBM
    FROM
    (
        SELECT APPOINTID , TruckerConfirm
        FROM CCC_TAHEADER
        WHERE
        DATEDIFF(D,RECEIVEDATE,'2010-10-01') <= 0
        AND DATEDIFF(D,RECEIVEDATE,GETDATE()) >= 0
    ) H
    INNER JOIN CCC_TADETAIL D
    ON D.APPOINTID = H.APPOINTID
    GROUP BY H.APPOINTID,H.TruckerConfirm
    )

    SELECT M.APPOINTID,M.LOADTYPE,c.TotalCBM,
     L_TruckSize3T, L_TruckSize5T, L_TruckSize8T, L_TruckSize10T, L_TruckSize12T,
     Size20, Size40, Size40R, Size40HQ, Size45,ReceiveDate
    FROM CCC_TAHEADER M
    INNER JOIN
    c
    ON M.APPOINTID = c.Appointid

  • 相关阅读:
    全文索引的书
    图片上传预览
    sqlserver 递归删除组织结构树
    dataset 转泛型list
    jquery easyui tree 异步加载数据
    sqlserver 禁用外键
    linx 实用操作命令二
    Compilation failed: this version of PCRE is not compiled with PCRE_UTF8 support at offset 0
    Centos linux php扩展安装步骤
    linux Apache和php配置
  • 原文地址:https://www.cnblogs.com/zhangchenliang/p/2021036.html
Copyright © 2020-2023  润新知