T-SQL笔记1:SELECT及SELECT高级应用

本章摘要

1:安装AdventureWorks

2:基本运算符和表达式

3:between

4:like

5:escape

6:TOP

7:GROUP BY

7.1:GROUP BY ALL

7.2:HAVING

8:SELECT字句技术

8.1:使用DISTINCT消除重复值

8.2:返回拼接的结果

8.3使用INTO字句

9:子查询

9.1:子查询类型

9.2:代替表达式的查询

  9.3:多层嵌套

10:比较使用 EXISTS 和 IN 的查询

11:联接
  11.1:使用衍生表

11.2:UNION

12:TABLESAMPLE

13:公共表表达式common_table_expression

1:安装AdventureWorks

本系列笔记均基于AdventureWorks数据库,有关AdventureWorks的安装帮助如下:

在 Management Studio 工具栏上,单击“文件”,指向“打开”,然后单击“文件”。

浏览到文件 instawdb.sql,并单击“打开”。该文件的默认位置为 C:\Program Files\Microsoft SQL Server\90\Tools\Samples\AdventureWorks OLTP。

运行脚本之前,在脚本中找到语句 SET @data_path = @sql_path + 'AWDB\';,并更改该语句使其指向 instawdb.sql 脚本的位置。例如,SET @data_path = 'C:\Program Files\Microsoft SQL Server\90\Tools\Samples\AdventureWorks OLTP\';。

执行脚本。

2:基本运算符和表达式

运算符 描述
!= 略
!> 略
!< 略
< 略
<= 略
<> 略
= 略
> 略
>= 略
ALL 比较标量值和单列集中的值。
ANY 比较标量值和单列集中的值。SOME 和 ANY 是等效的
BETWEEN 自动根据SQL的型别进行取值
CONTAINS 为单词或短语执行模糊搜索
ESCAPE 指定要以字面值形式搜索,而不是被解释为通配符
EXISTS 指定一个子查询,测试行是否存在
FREETEXT 根据意思,而不是字面值来搜索数据中的单词
IN WHERE color in (‘red’,‘blue’)
IS NOT NULL 略
IS NULL 检测NULL值
LIKE 根据通配符进行模式匹配
NOT BETWEEN 略
NOT IN 略
NOT LIKE 略
SOME 比较标量值和单列集中的值。SOME 和 ANY 是等效的

3:between

使用:

select SalesOrderID, ShipDate from Sales.SalesOrderHeader
where ShipDate between '7/28/2002' and '7/29/2002'

结果:将会返回17条语句。

也许有人会用,使用:

where'7/28/2002' < ShipDate and ShipDate < '7/29/2002'

不行吗?答案是不行。结果会返回0。

4:like

存在如下通配符,

%:0~N个任意字符;

_:1个字符;

[]:指定范围或列表中的任何单个字符;

[^]:指定不再范围中的任何单个字符;

5:escape

where name like ‘b/B%’ escape ‘/’

解析:表示全部以‘b/B’开头的name,其中/不理解为通配符。

6:TOP

top允许根据定义的行的数量或者百分比查询出开始的N行。如:

select top 10 from …

或者:

declare @percentage float

set @percentage =1

select top (@percentage)  percent * from Sales.SalesOrderHeader

7:GROUP BY

指定用来放置输出行的组。如果 SELECT 子句 <select list> 中包含聚合函数,则 GROUP BY 将计算每组的汇总值。

上面这句话不太好理解,更好的理解应该解释为:

“由于在SELECT字句中使用了聚合函数,未聚合的列必须出现在GROUP BY子句中。”

select OrderDate, sum(totalDue) TotalDueByOrderDate from Sales.SalesOrderHeader
where ShipDate between '7/28/2002' and '7/29/2002'
group by OrderDate

结果:

(2 行受影响)

7.1:GROUP BY ALL

在上面的代码中,加入ALL,即:

select OrderDate, sum(totalDue) TotalDueByOrderDate from Sales.SalesOrderHeader
where ShipDate between '7/28/2002' and '7/29/2002'
--group by OrderDate
group by all OrderDate

结果:

Warning: Null value is eliminated by an aggregate or other SET operation.

(1124 行受影响)

这说明:ALL包含所有组和结果集,甚至包含那些其中任何行都不满足 WHERE 子句指定的搜索条件的组和结果集。如果指定了 ALL,将对组中不满足搜索条件的汇总列返回空值。

7.2:HAVING

指定组或聚合的搜索条件。HAVING 只能与 SELECT 语句一起使用。HAVING 通常在 GROUP BY 子句中使用。如果不使用 GROUP BY 子句,则 HAVING 的行为与 WHERE 子句一样。

相当于对GROUP之前的查询内容进行再一次的条件检索。

以下示例使用简单 HAVING 子句从 SalesOrderDetail 表中检索超过 $100000.00 的每个 SalesOrderID 的总计。

SELECT SalesOrderID, SUM(LineTotal) AS SubTotal
FROM Sales.SalesOrderDetail
--where ModifiedDate between '7/28/2002' and '7/29/2002'
GROUP BY SalesOrderID
HAVING SUM(LineTotal) > 100000.00
--HAVING SalesOrderID = 43875
--HAVING ModifiedDate between '7/28/2002' and '7/29/2002' --error
ORDER BY SalesOrderID ;

8:SELECT字句技术

        SELECT字句技术有很多,除了最简单的拼接等,下面介绍个人认为最有用的。

8.1:使用DISTINCT消除重复值

select * FROM HumanResources.Employee

结果:(290 行受影响)
select DISTINCT HireDate FROM HumanResources.Employee

结果:(164 行受影响)

说明已经将重复的抵消了。

8.2:返回拼接的结果

DECLARE @Shifts varchar(20)
SET @Shifts = ''
SELECT @Shifts = @Shifts + s.Name + ',' FROM HumanResources.Shift s
SELECT @Shifts

返回的结果为:Day,Evening,Night,

这对于我们处理简单的查询并提高效率有很大的好处。

8.3使用INTO字句

INTO字句用来创建新表(对我来说便是备份数据)。

一种典型的用法是复制数据到新表(这个新表可以被创建为永久表、临时表或全局临时表),如下代码:

SELECT CustomerID, Name, SalesPersonID, Demographics
INTO  Store_Archive
FROM Sales.Store

结果:(701 行受影响)

说明,1:创建了新表Store_Archive,2:有701行数据被复制到了Store_Archive。

当然,如果你仅仅想创建新表,而不想复制任何数据,有一个简洁的方法是:

SELECT CustomerID, Name, SalesPersonID, Demographics
INTO  Store_Archive
FROM Sales.Store
WHERE 1=0

9:子查询

子查询是一个嵌套在 SELECT、INSERT、UPDATE 或 DELETE 语句或其他子查询中的查询。任何允许使用表达式的地方都可以使用子查询。

联接总是可以表示为子查询。子查询经常(但不总是)可以表示为联接。这是因为联接是对称的:无论以何种顺序联接表 A 和 B,都将得到相同的结果。而对子查询来说,情况则并非如此。

使用联接而不使用子查询处理该问题及类似问题的一个不同之处在于,联接使您可以在结果中显示多个表中的列。例如,如果要在结果中包括产品子类别的名称,则必须使用联接版本。

9.1:子查询类型

可以在许多位置指定子查询(必须全部掌握):

9.2:代替表达式的查询

必须着重说说代替表达式的子查询。在 Transact-SQL 中,除了在 ORDER BY 列表中以外,在 SELECT、UPDATE、INSERT 和 DELETE 语句中任何能够使用表达式的地方都可以用子查询替代。

以下示例说明如何使用此增强功能。此查询找出所有山地车产品的价格、平均价格以及两者之间的差价。

USE AdventureWorks;
GO
SELECT Name, ListPrice,
(SELECT AVG(ListPrice) FROM Production.Product) AS Average,
ListPrice - (SELECT AVG(ListPrice) FROM Production.Product)
AS Difference
FROM Production.Product
WHERE ProductSubcategoryID = 1
 
9.3:多层嵌套

子查询自身可以包括一个或多个子查询。一个语句中可以嵌套任意数量的子查询。

以下查询将查找作为销售人员的雇员的姓名。

Use AdventureWorks;
GO
SELECT LastName, FirstName
FROM Person.Contact
WHERE ContactID IN
(SELECT ContactID
FROM HumanResources.Employee
WHERE EmployeeID IN
(SELECT SalesPersonID
FROM Sales.SalesPerson)
 

10:比较使用 EXISTS 和 IN 的查询

以下示例比较了两个语义等同的查询。第一个查询使用 EXISTS,第二个查询使用 IN。

USE AdventureWorks ;
GO
SELECT a.FirstName, a.LastName
FROM Person.Contact AS a
WHERE EXISTS
(SELECT *
FROM HumanResources.Employee AS b
WHERE a.ContactId = b.ContactID
AND a.LastName = 'Johnson');
GO

下面的查询使用 IN。

USE AdventureWorks ;
GO
SELECT a.FirstName, a.LastName
FROM Person.Contact AS a
WHERE a.LastName IN
(SELECT a.LastName
FROM HumanResources.Employee AS b
WHERE a.ContactId = b.ContactID
AND a.LastName = 'Johnson');
GO

以下是其中任一查询的结果集。

FirstName                                          LastName
-------------------------------------------------- ----------
Barry Johnson
David Johnson
Willis Johnson
(3 row(s) affected)
 
11:联接
   通过联接,可以从两个或多个表中根据各个表之间的逻辑关系来检索数据。
   联接条件中用到的列不必具有相同的名称或相同的数据类型。但如果数据类型不相同,则必须兼容,或者是可由 SQL Server 进行隐式转换的类型。

联接可分为以下几类:

  • 内部联接(典型的联接运算,使用类似于 = 或 <> 的比较运算符)。内部联接包括同等联接和自然联接。
    内部联接使用比较运算符根据每个表的通用列中的值匹配两个表中的行。例如,检索 students 和 courses 表中学生标识号相同的所有行。
  • 外部联接。外部联接可以是左向外部联接、右向外部联接或完整外部联接。
    在 FROM 子句中可以用下列某一组关键字来指定外部联接:
    • LEFT JOIN 或 LEFT OUTER JOIN。
      左向外部联接的结果集包括 LEFT OUTER 子句中指定的左表的所有行,而不仅仅是联接列所匹配的行。如果左表的某一行在右表中没有匹配行,则在关联的结果集行中,来自右表的所有选择列表列均为空值。
    • RIGHT JOIN 或 RIGHT OUTER JOIN
      右向外部联接是左向外部联接的反向联接。将返回右表的所有行。如果右表的某一行在左表中没有匹配行,则将为左表返回空值。
    • FULL JOIN 或 FULL OUTER JOIN
      完整外部联接将返回左表和右表中的所有行。当某一行在另一个表中没有匹配行时,另一个表的选择列表列将包含空值。如果表之间有匹配行,则整个结果集行包含基表的数据值。
  • 交叉联接
    交叉联接将返回左表中的所有行。左表中的每一行均与右表中的所有行组合。交叉联接也称作笛卡尔积。

11.1:使用衍生表

衍生表是指在FROM字句中作为表的SELECT语句。

SELECT DISTINCT s.PurchaseOrderNumber
FROM Sales.SalesOrderHeader s
INNER JOIN ( SELECT SalesOrderID
    FROM Sales.SalesOrderDetail
    WHERE UnitPrice BETWEEN 1000 AND 2000) d ON
    s.SalesOrderID = d.SalesOrderID

11.2:UNION

   将两个或更多查询的结果合并为单个结果集,该结果集包含联合查询中的所有查询的全部行。

下面列出了使用 UNION 合并两个查询结果集的基本规则:

  • 所有查询中的列数和列的顺序必须相同。
  • 数据类型必须兼容。

SELECT ProductModelID, Name FROM Production.ProductModel WHERE ProductModelID NOT IN (3, 4) UNION SELECT ProductModelID, Name FROM dbo.Gloves ORDER BY Name ;

12:TABLESAMPLE

TABLESAMPLE 子句将从 FROM 子句中的表返回的行数限制到样本数或行数的某一百分比。例如:

SELECT FirstName, LastName FROM Person.Person TABLESAMPLE (10 PERCENT) ;

SELECT FirstName, LastName FROM Person.Person TABLESAMPLE (100 ROWS) ;

13:公共表表达式common_table_expression

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

USE AdventureWorks;
GO
WITH DirReps(ManagerID, DirectReports) AS
(
    SELECT ManagerID, COUNT(*)
    FROM HumanResources.Employee AS e
    WHERE ManagerID IS NOT NULL
    GROUP BY ManagerID
)
SELECT ManagerID, DirectReports
FROM DirReps
ORDER BY ManagerID;
GO

SQL笔记1:SELECT及SELECT高级应用的更多相关文章

  1. SQL必知必会 -------- SELECT、注释

    主要是看<SQL必知必会>第四版的书,而写的一些SQL笔记,红色的是方便以后查询的sql语句,工作中主要是使用mysql数据库,所以笔记也是围绕mysql而写的. 下文调试的数据表sql语 ...

  2. SQL Server游标 C# DataTable.Select() 筛选数据 什么是SQL游标? SQL Server数据类型转换方法 LinQ是什么? SQL Server 分页方法汇总

    SQL Server游标   转载自:http://www.cnblogs.com/knowledgesea/p/3699851.html. 什么是游标 结果集,结果集就是select查询之后返回的所 ...

  3. sql: sybase与oracle中insert into select和select into的用法

    1. sybase与oracle中insert into select和select into的用法 http://wjlvivid.iteye.com/blog/1921679 Sybase 一.首 ...

  4. SQL Server中 SET 和 SELECT 赋值有什么区别?

    SQL Server 中对已经定义的变量赋值的方式用两种,分别是 SET 和 SELECT.对于这两种方式的区别,SQL Server 联机丛书中已经有详细的说明,但很多时候我们并没有注意,其实这两种 ...

  5. sql server set赋值和select 赋值的区别以及使用方法

    sqlserver存储过程中SELECT 与 SET 对变量赋值的区别   (备注:虽然变量赋值使用方法已经不是问题,但是,了解一下select和set赋值的区别,还是提高了不少认识.应该有很多人并不 ...

  6. SQL学习(三)Select语句:返回前多少行数据

    在实际工作中,我们可能根据某种排序后,只需要显示前多少条数据,此时就需要根据不同的数据库,使用不同的关键字 一.SQL Server/Access select top 数量/百分比 from tab ...

  7. 你确定 SQL 查询都是以 SELECT 开始的?

    很多 SQL 查询都是以 SELECT 开始的. 不过,最近我跟别人解释什么是窗口函数,我在网上搜索"是否可以对窗口函数返回的结果进行过滤"这个问题,得出的结论是"窗口函 ...

  8. SQL语句之查询(SELECT)

    目录 SQL语句之查询(SELECT) 简单查询 限定查询 模糊查询 排序查询 多表查询 SQL语句之查询(SELECT) SQL是用于访问和处理数据库的标准计算机语言: 中文:结构化查询语言:英文全 ...

  9. SQL 笔记 By 华仔

    -------------------------------------读书笔记------------------------------- 笔记1-徐 最常用的几种备份方法 笔记2-徐 收缩数据 ...

随机推荐

  1. 通过Daffodil for VS使VS2010的IDE可以用VC6 VC7.1 VC9等编译器进行项目编译

    本文内容中的部分资料和知识来源于网络,具体引用出处不明. VS的IDE从VC6到VS2010的变化可谓是天翻地覆,最新的VS2010有一个特性就是支持多显示器开发,这无疑为我们的开发带来很大的便利. ...

  2. 安装lxml时gcc: internal compiler error: Killed (program cc1)的解决方法

    在安装lxml时出现如下错误 gcc: internal compiler error: Killed (program cc1) 通过查看dmesg发现下述错误信息[2517343.500178] ...

  3. git学习:忽略部分文件

    第二部分:自定义Git 有些时候,你必须把某些文件放到Git工作目录中,但又不能提交它们,比如保存了数据库密码的配置文件,数据库文件,图片等等,每次git status都会显示Untracked fi ...

  4. MVC 访问IFrame页面Session过期后跳转到登录页面

    Web端开发时,用户登录后往往会通过Session来保存用户信息,Session存放在服务器,当用户长时间不操作的时候,我们会希望服务器保存的Session过期,这个时候,因为Session中的用户信 ...

  5. Delphi 查找标题已知的窗口句柄,遍历窗口控件句柄(转)

    用我的方法来控制其他程序窗体上的窗口控件,必须先了解什么是 回调函数.我的理解是这样的: 回 调函数写出来不是自己的程序去调用的,反而是让其他的东西去调用,比如windows操作系统,比如其他的程序等 ...

  6. JavaScript的学习4

    一.Array对象 ArrayObject.reverse()   将数组进行翻转 ArrayObject.shift()     删除数组中的第一个元素并将其返回 ArrayObject.unshi ...

  7. Postgresql 迁移随笔一

    最近忙于MSSQL 迁移到Postgresql的工程,在这里记录一下迁移遇到的问题以及解法. 程序语言:java 要求,根据不同的driver可以同时支援多种数据库,目前主要为MSSQL 和Postg ...

  8. Win8.1安装Visual Studio 2015提示需要KB2999226

    http://www.microsoft.com/zh-cn/download/details.aspx?id=48234 ,下载解压出来就有了,里面包含Vista.Win7.Win8.1三个系统x8 ...

  9. window.frame

    定义和用法 frames 属性返回窗口中所有命名的框架. 该集合是 Window 对象的数组,每个 Window 对象在窗口中含有一个框架或 <iframe>.属性 frames.leng ...

  10. logging 日志模块学习

    logging 日志模块,用于记录系统在运行过程中的一些关键信息,以便于对系统的运行状况进行跟踪,所以还是灰常重要滴,下面我就来从入门到放弃的系统学习一下日志既可以在屏幕上显示,又可以在文件中体现. ...