T-SQL 学习笔记 Chapter 6 子查询、表表达式 和排名函数 (一)

子查询:标量子查询
              相关子查询
              多值子查询
              独立子查询
 
表表达式:派生表和公用表表达式CTE
排名函数:行号 row number,
                   排名rank,
                   密度排名dense rank,
                   分组NTILE
1.标量独立子查询
SELECT orderid FROM Sales.Orders
WHERE empid = 
  (SELECT empid FROM HR.Employees
   -- also try with N'Kollar' and N'D%'
   WHERE lastname LIKE N'Davis');
SELECT orderid FROM Sales.Orders
WHERE empid = 
  (SELECT empid FROM HR.Employees
   -- also try with N'Kollar' and N'D%'
   WHERE lastname LIKE N'Davis');
子查询返回一条或者0条数据 查询顺利执行,返回多条数据则报错。
 
使用group by 和distinct count 来解决关系除法的问题。
 
2.相关子查询
   相关子查询是引用了在外部查询中出现的列的子查询。从逻辑上讲,子查询会为外部查询的每一行进行一次计算。
SELECT * FROM SYSDATABASES--查询所有的表
 
查询最近的订单
索引:
 
CREATE UNIQUE INDEX idx_eid_od_oid
  ON Sales.Orders(empid, orderdate, orderid);
CREATE UNIQUE INDEX idx_eid_od_rd_oid
  ON Sales.Orders(empid, orderdate, requireddate, orderid);
GO
DROP INDEX Sales.Orders.idx_eid_od_oid;
DROP INDEX Sales.Orders.idx_eid_od_rd_oid;
 
SELECT orderid, custid, empid, orderdate, requireddate
FROM Sales.Orders AS O1
WHERE orderdate =
  (SELECT MAX(orderdate)
   FROM Sales.Orders AS O2
   WHERE O2.empid = O1.empid)
  AND orderid =
  (SELECT MAX(orderid)
   FROM Sales.Orders AS O2
   WHERE O2.empid = O1.empid
     AND O2.orderdate = O1.orderdate);
 
-- Most recent order for each employee, nesting subqueries
-- Tiebreaker: max order id
 
SELECT orderid, custid, empid, orderdate, requireddate
FROM Sales.Orders AS O1
WHERE orderid =
  (SELECT MAX(orderid)
   FROM Sales.Orders AS O2
   WHERE O2.empid = O1.empid
     AND O2.orderdate =
       (SELECT MAX(orderdate)
        FROM Sales.Orders AS O3
        WHERE O3.empid = O1.empid));
 
-- Most recent order for each employee
-- Tiebreaker: max requireddate, max orderid
SELECT orderid, custid, empid, orderdate, requireddate
FROM Sales.Orders AS O1
WHERE orderdate =
  (SELECT MAX(orderdate)
   FROM Sales.Orders AS O2
   WHERE O2.empid = O1.empid)
  AND requireddate =
  (SELECT MAX(requireddate)
   FROM Sales.Orders AS O2
   WHERE O2.empid = O1.empid
     AND O2.orderdate = O1.orderdate)
  AND orderid =
  (SELECT MAX(orderid)
   FROM Sales.Orders AS O2
   WHERE O2.empid = O1.empid
     AND O2.orderdate = O1.orderdate
     AND O2.requireddate = O1.requireddate);

  

3.EXISTS
  为社么not in和not exist 对于查询有空值的时候,结果不同
4.查询最小的缺失键值
5.不常用的ALL SOME ANY
6. 派生表
6.1 使用参数
  每年由雇员3处理的客户数量
 
DECLARE @EMPID AS INT=3
 
SELECT Y ,count( DISTINCT cusTID) AS NUMBER FROM
(SELECT  year(orderdate) AS Y,CUSTID FROM  SALES.ORDERS WHERE EMPID=@EMPID)T
GROUP BY Y

  

 
6.2嵌套---不推荐
返回客户数量超过70的订单年份和该年份的客户数量
SELECT Y ,count( DISTINCT custid) AS NUMBER FROM
(select year(orderdate) y, custid from SALES.ORDERS) t
group by y having count( DISTINCT custid)>70
 
7.公用表表达式CTE
公用表表达式类似于派生表 两者均无法使用ORDERBY 除非包含top,每一列都必须有列名
7.1两种声明方式
-- Inline column aliasing
WITH C AS
(
  SELECT YEAR(orderdate) AS orderyear, custid
  FROM Sales.Orders
)
SELECT orderyear, COUNT(DISTINCT custid) AS numcusts
FROM C
GROUP BY orderyear;
 
-- External column aliasing
WITH C(orderyear, custid) AS
(
  SELECT YEAR(orderdate), custid
  FROM Sales.Orders
)
SELECT orderyear, COUNT(DISTINCT custid) AS numcusts
FROM C
GROUP BY orderyear;
GO
7.2 在CTE中使用变量
 
DECLARE @empid AS INT = 3;

WITH C AS
(
  SELECT YEAR(orderdate) AS orderyear, custid
  FROM Sales.Orders
  WHERE empid = @empid
)
SELECT orderyear, COUNT(DISTINCT custid) AS numcusts
FROM C
GROUP BY orderyear;
GO

  

7.3多CTE CTE不能在内部定义另一个CTE 但是每一个CTE都可以引用前面的CTE
-- Defining multiple CTEs
WITH C1 AS
(
  SELECT YEAR(orderdate) AS orderyear, custid
  FROM Sales.Orders
),
C2 AS
(
  SELECT orderyear, COUNT(DISTINCT custid) AS numcusts
  FROM C1
  GROUP BY orderyear
)
SELECT orderyear, numcusts
FROM C2
WHERE numcusts > 70;

  

7.4多引用 可以重复引用一个CTE
-- Multiple references
WITH YearlyCount AS
(
  SELECT YEAR(orderdate) AS orderyear,
    COUNT(DISTINCT custid) AS numcusts
  FROM Sales.Orders
  GROUP BY YEAR(orderdate)
)
SELECT Cur.orderyear, 
  Cur.numcusts AS curnumcusts, Prv.numcusts AS prvnumcusts,
  Cur.numcusts - Prv.numcusts AS growth
FROM YearlyCount AS Cur
  LEFT OUTER JOIN YearlyCount AS Prv
    ON Cur.orderyear = Prv.orderyear + 1;
GO

  

7.5可以通过CTE修改数据
7.5.1 删除重复客户
IF OBJECT_ID('Sales.CustomersDups') IS NOT NULL
  DROP TABLE Sales.CustomersDups;
GO

SELECT 
  custid, companyname, contactname, contacttitle, address,
  city, region, postalcode, country, phone, fax
INTO Sales.CustomersDups
FROM Sales.Customers CROSS JOIN (VALUES(1),(2),(3)) AS Nums(n);

-- Modifying data through CTEs
WITH CustsDupsRN AS
(
  SELECT *,
    ROW_NUMBER() OVER(PARTITION BY custid ORDER BY (SELECT 0)) AS rn
  FROM Sales.CustomersDups
)
DELETE FROM CustsDupsRN
WHERE rn > 1;
GO

7.6视图和内联函数中 使用CTE
   
-- UDF with CTE
IF OBJECT_ID('dbo.EmpYearCustCnt') IS NOT NULL
  DROP FUNCTION dbo.EmpYearCustCnt;
GO
CREATE FUNCTION dbo.EmpYearCustCnt(@empid AS INT) RETURNS TABLE
AS
RETURN
  WITH CEmpYearCustCnt AS
  (
    SELECT YEAR(orderdate) AS orderyear,
      COUNT(DISTINCT custid) AS numcusts
    FROM Sales.Orders
    WHERE empid = @empid
    GROUP BY YEAR(orderdate)
  )
  SELECT * FROM CEmpYearCustCnt;
GO

-- Querying UDF with CTE
SELECT * FROM dbo.EmpYearCustCnt(3) AS T;
GO

7.7 递归CTE

 太高深了 么看懂

253 (268 / 601)

 
 
 
 
 
 
 
 
 
 

猜你喜欢

转载自www.cnblogs.com/coderinprague/p/11425251.html
今日推荐