T-SQL with关键字
T-SQL with关键字
Select字句在逻辑上是SQL语句最后进行处理的最后一步,所以,以下查询会发生错误:
SELECT
YEAR(OrderDate) AS OrderYear,
COUNT(DISTINCT CustomerID) AS NumCusts
FROM dbo.Orders
GROUP BY OrderYear;
因为group by是在Select之前进行的,那个时候orderYear这个列并没有形成。
如果要查询成功,可以像下面进行修改:
SELECT OrderYear, COUNT(DISTINCT CustomerID) AS NumCusts
FROM (SELECT YEAR(OrderDate) AS OrderYear, CustomerID
FROM dbo.Orders) AS D
GROUP BY OrderYear;
还有一种很特殊的写法:
SELECT OrderYear, COUNT(DISTINCT CustomerID) AS NumCusts
FROM (SELECT YEAR(OrderDate), CustomerID
FROM dbo.Orders) AS D(OrderYear, CustomerID)
GROUP BY OrderYear;
在作者眼里,他是非常喜欢这种写法的,因为更清晰,更明确,更便于维护。
在查询中使用参数定向产生一批结果,这个技巧没有什么好说的。
嵌套查询,在处理逻辑上是从里向外进行执行的。
多重引用,有可能你的SQL语句包含了多次从一个表进行查询后进行连接组合。比如你要比较每年的顾客数同先前年的顾客数的变化,所以你的查询就必须JOIN了2个相同的表的实例,这也是不可避免的。
Common Table Expressions (CTE)
CTE是在SQL2005新加入的一种表的表示类型。
它的定义如下:
WITH cte_name
AS
(
cte_query
)
outer_query_refferring to_cte_name;
注意:因为在标准的T-SQL语言中已经包含了WITH关键字,所以为了区分,CTE在语句的结尾加上了“;”作为停止符。
CTE实例一(结果集别名)
WITH C AS
(
SELECT YEAR(OrderDate) AS OrderYear, CustomerID
FROM dbo.Orders
)
SELECT OrderYear, COUNT(DISTINCT CustomerID) AS NumCusts
FROM C
GROUP BY OrderYear;
当然,作者本人有更推荐的写法:
WITH C(OrderYear, CustomerID) AS
(
SELECT YEAR(OrderDate), CustomerID
FROM dbo.Orders
)
SELECT OrderYear, COUNT(DISTINCT CustomerID) AS NumCusts
FROM C
GROUP BY OrderYear;
CTE实例二(多重CTEs)
WITH C1 AS
(
SELECT YEAR(OrderDate) AS OrderYear, CustomerID
FROM dbo.Orders
),
C2 AS
(
SELECT OrderYear, COUNT(DISTINCT CustomerID) AS NumCusts
FROM C1
GROUP BY OrderYear
)
SELECT OrderYear, NumCusts
FROM C2
WHERE NumCusts > 70;
CTE实例三(多重引用)
WITH YearlyCount AS
(
SELECT YEAR(OrderDate) AS OrderYear,
COUNT(DISTINCT CustomerID) AS NumCusts
FROM dbo.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;
CTE实例四(修改数据)
1.把从customer表查询出来的结果,动态的组装进新表CustomersDups里:
IF OBJECT_ID('dbo.CustomersDups') IS NOT NULL
DROP TABLE dbo.CustomersDups;
GO
WITH CrossCustomers AS
(
SELECT 1 AS c, C1.*
FROM dbo.Customers AS C1, dbo.Customers AS C2
)
SELECT ROW_NUMBER() OVER(ORDER BY c) AS KeyCol,
CustomerID, CompanyName, ContactName, ContactTitle, Address,
City, Region, PostalCode, Country, Phone, Fax
INTO dbo.CustomersDups
FROM CrossCustomers;
2.使用CTE移除数据,只保留CustomerDups表里同一CustomerID里KeyCol为最大的记录。
WITH JustDups AS
(
SELECT * FROM dbo.CustomersDups AS C1
WHERE KeyCol <
(SELECT MAX(KeyCol) FROM dbo.CustomersDups AS C2
WHERE C2.CustomerID = C1.CustomerID)
)
DELETE FROM JustDups;
CTE实例五(对象容器)
即提供了封装的能力,有利于组件化的编程。作者额外的提醒,CTE无法直接内嵌,但是可以通过把CTE封装进一个对象容器里并从一个外部的CTE里对这容器的数据进行查询而实现内嵌。
作者也说明了,使用CTEs在VIEW和UDFs里是没有什么价值的。
有个例子,如下:
CREATE VIEW dbo.VYearCnt
AS
WITH YearCnt AS
(
SELECT YEAR(OrderDate) AS OrderYear,
COUNT(DISTINCT CustomerID) AS NumCusts
FROM dbo.Orders
GROUP BY YEAR(OrderDate)
)
SELECT * FROM YearCnt;
CTE实例六(CTEs的递归)
作者给了一个例子,来讲述这个在SQL2005的新内容,CTEs的递归。
根据employeeId,返回此员工的信息,并包含所有下级员工的信息。(等级关系基于empolyeeId和reportsTo的属性)所返回的结果包含下列字段,employeeId,reportsTo,FirstName,LastName。
作者在这里,给予了一个最佳的索引方式:
CREATE UNIQUE INDEX idx_mgr_emp_ifname_ilname
ON dbo.Employees(ReportsTo, EmployeeID)
INCLUDE(FirstName, LastName);
作者的解释: 这个索引将通过一个单独的查询(局部扫描)来取得每个经理的直接下级。Include(FristName,LastName)加在这里,即是覆盖列。
小知识:什么Include索引?
Include索引是SQL2005的新功能。Include索引的列并不影响索引行的物理存储顺序,他们作为一个挂件‘挂在'索引行上。挂这些‘挂件'的目的在于,只需要扫描一把索引就获得了这些附加数据。
回到作者的例子上,下面是递归的代码:
WITH EmpsCTE AS
(
SELECT EmployeeID, ReportsTo, FirstName, LastName
FROM dbo.Employees
WHERE EmployeeID = 5
UNION ALL SELECT EMP.EmployeeID, EMP.ReportsTo, EMP.FirstName, EMP.LastName
FROM EmpsCTE AS MGR
JOIN dbo.Employees AS EMP
ON EMP.ReportsTo = MGR.EmployeeID
)
SELECT * FROM EmpsCTE;
理解:一个递归的CTE包含了至少2个查询,第一个查询在CTE的身体里类似于一格锚点。这个锚点仅仅返回一个有效的表,并作为递归的一个锚。从上的例子看出来,锚点仅仅返回了一个employeeID = 5 的一行。然后的第2个查询是作为递归成员。当查询到下属成员的结果为空时,此递归结束。
如果你担心递归会造成永久循环,你可以使用下面的表达:
WITH cte_name AS (cte_body) outer_query OPTION (MAXRECURSION n);
默认的n为100,当n=0时,无限制。
T-SQL with关键字的更多相关文章
- //sql过滤关键字
//sql过滤关键字 public static bool CheckKeyWord(string sWord) { //过滤关键字 string StrKeyWord = @"select ...
- SQL保留关键字不能用作表名
com.microsoft.sqlserver.jdbc.SQLServerException: 关键字 'User' 附近有语法错误. 一看就是SQL语句错误,发现控制台console上打印出来的S ...
- 单表:SQL语句关键字的执行顺序
表和数据: -- 创建表 CREATE TABLE `person` ( `id` ) NOT NULL AUTO_INCREMENT, `name` ) NOT NULL, `age` ) ', ` ...
- sql的关键字
整理一下sql的关键字,一直都在用,只是很少去整理,所以今天简单整理一下,主要是整理CRUD的一些关键字. 写在前面:sql 不区分大小写 select 简单查询语句 select columnNam ...
- mybatis plus 使用 SQL 保留字(关键字)
MybatisPlus:使用SQL保留字(关键字)的操作 必须要手动在 entity 的字段上加注解,否则最终会报错,因为 mybatis 或者 mybatis plus 不会自动处理
- SQL数据库关键字和列名冲突处理
在设计SQL数据库的时候可能由于考虑不全,使列名和数据库内关键字冲突,可能导致Query不能被正确识别,对列名要加[]处理.
- 容斥原理及SQL in关键字在EF中的应用
突然意识到文字的重要性,于是开始写了第一个篇博客,博客目的紧紧为记录,以便温故. 同时也希望抛砖能达到引玉的作用,欢迎各位来发表自己的感想与想法,以此达到相互学习促进! 背景: 在做百度地图电子围栏的 ...
- 【转】SQL 常用关键字释义和用法
转自: http://blog.csdn.net/iamwangch/article/details/8093933 下面 是 从网络上整理 出来的 SQL 关键字和 常用函数的 释义和简单用 ...
- SQL中关键字的执行顺序
作为一个SQL新手,看到每种不熟悉的关键字时已经够迷茫了,可往往见到的语句关键字顺序还是各种各样,太难理解了.网上搜索了两篇文章,总结一下: 关于Sql关键字SELECT FROM GROUP ORD ...
- SQL基础 关键字
SQL语言类型 数据定义:create/alter/drop table/trigger/index/function/存储过程/约束/…数据操纵:select/update/insert/delet ...
随机推荐
- redis实现分布式锁工具类 灰常好用
public interface RedisDistributionLock { /** * 加锁成功,返回加锁时间 * @param lockKey * @param threadName * @r ...
- Lisp em SCU - 4490 (强大的map用法)
Time Limit: 1000 MS Memory Limit: 131072 K Description There are two lists and they may be intersect ...
- (bc 1001) hdu 6015 skip the class
Skip the Class Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) T ...
- 【BZOJ 4631】4631: 踩气球 (线段树)
4631: 踩气球 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 316 Solved: 153 Description 六一儿童节到了, SHUX ...
- USACO 2017 FEB Platinum nocross DP
题目大意 上下有两个长度为n.位置对应的序列A.B,其中数的范围均为1~n.若abs(A[i]-B[j]) <= 4,则A[i]与B[j]间可以连一条边.现要求在边与边不相交的情况下的最大的连边 ...
- hust 1590 - 方块游戏 数学
1590 - 方块游戏 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/problem/show/1590 D ...
- Qt on android 蓝牙开发(控制小车)
因为要做一个用蓝牙控制小车的app,就用着QT搞了下,网上关于QT蓝牙开发的资料比较少,我在这里记录下过程希望对看到了人有所帮助 首先在项目文件里添加 QT += bluetooth 这样就可以用QT ...
- 【原】Project configuration is not up-to-date with pom.xml
导入一个Maven项目之后发现有一个如下的错误: Project configuration is not up-to-date with pom.xml. Run project configura ...
- Oracle密码忘记了解决办法
Oracle密码忘记了怎么办?有时候我们可能忘记了一个用户的密码,但是又需要以这个用户做一些操作,又不能去修改掉这个用户的密码,这个时候,就可以利用一些小窍门,来完成操作.采用如下方法可以修改密码: ...
- 读CRecordset
void CDictCol::LoadDictCol(void) { // 加载数据字典信息 CString cstrSql; cstrSql.Format("SELECT dc.TblID ...