子查询:标量子查询
相关子查询
多值子查询
独立子查询
表表达式:派生表和公用表表达式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)