SQL-SELECT查询

来自必知必会的实践

简单查询

1. 检索单个列

– 查询产品表的产品名

SELECT prod_name FROM Products;
2. 检索多个列,列名以逗号分隔

– 查询产品表的ID,产品名,产品价格列

SELECT prod_id,prod_name,prod_price
FROM Products;
3. 检索所有列,使用 * 通配符
  • 除非必要最好别用,因为检索不需要的列会降低检索和应用程序的性能。
  • 优点:可以检索出名字未知的列,不用明确指定列名
SELECT * FROM Products;
4. 检索不同的值,使用DISTINCT关键字

像集合一样只包含不一样的元素,使用DISTINCT关键字:独一无二的值。
– DISTINCT必须直接放在列名的前面。
– 不能部分使用DISTINCT,该关键字作用于列出的所有列,不仅仅是跟在其后的那一列,变成了组合的唯一性。

-- 检索产品表中的供应商都有谁
SELECT DISTINCT vend_id,prod_price
FROM Products;
5. 限制返回结果是前几行

sql server中使用TOP关键字限制最多返回几行,不同的DBMS语法不一样

-- 检索产品表产品名列的前5行
SELECT TOP 5 prod_name
FROM Products;

进阶查询-排序

– 对查询结果排序,使用ORDER BY子句
(因为数据显示的顺序可能不是我们想要的,如果不明确规定排序顺序,则不应假定检索出的顺序有意义)
– 关键字+数据构成子句
– 按单个列排序,ORDER BY+列名
ORDER BY子句必须是SELECT中最后一条子句
– ORDER BY中的列名可以是非检索的列

-- 查询产品表的产品名,按产品名排序
SELECT prod_name
FROM Products
ORDER BY prod_name          -- 字符型数据列以字母顺序排序

– 按多个列排序,指定列名,用逗号分隔,先按第一个列排序,若相同,再以第二个列排序

-- 查询产品表的产品ID、产品名,产品价格,首先按价格排序,然后按名称排序
SELECT prod_id,prod_price,prod_name       -- 指定列名的顺序就是最终结果显示的列的顺序
FROM Products
ORDER BY prod_price,prod_name;

– 该语句等价于按相对列位置排序,即ORDER BY子句中的列名以查询选择的列中的位置代替,缺点是不能按非检索列进行排序了

SELECT prod_id,prod_price,prod_name       -- 指定列名的顺序就是最终结果显示的列的顺序
FROM Products
ORDER BY 2,3;

– 排序单个列时指定排序方向,升序降序(字符型从Z到A),默认升序,降序是DESC关键字,写在排序列后面

-- 查询产品表的产品ID、产品价格、产品名,按价格降序排序
SELECT prod_id,prod_price,prod_name
FROM Products
ORDER BY prod_price DESC;

– 对多个列排序时指定排序方向
– DESC关键字只作用在直接位于其前面的列名,若对多列降序排序,必须每列指定DESC,升序可不写ASC

-- 降序排序产品,相同的话再降序排序产品名
SELECT prod_id,prod_price,prod_name
FROM Products
ORDER BY prod_price DESC,prod_name DESC;  --ORDER BY prod_price DESC,prod_name;

note:字母的大小写对于排序顺序的影响?取决于具体的数据库设置方式
conclude:ORDER BY子句必须是select语句中的最后一条子句。根据需要,可以利用它在一个或多个列上进行排序。

过滤数据-WHERE子句指定搜索条件

– 一般只需要检索满足条件的行,WHERE子句在FROM子句之后给出

-- 检索产品表中价格为3.49的产品(名称和价格)
SELECT prod_name,prod_price
FROM Products
WHERE prod_price=3.49;

note:为什么不把所有数据检索出来一起发送到客户端的应用程序,让应用程序检索呢?
– 数据在应用层过滤极为不妥,因为让客户端应用或开发语言处理数据库的工作会极大影响应用的性能,而且所有数据是多余的,浪费资源。因此应该在数据库检索好需要的数据再传给客户端代码

ORDER BY子句放在WHERE子句之后

– WHERE子句操作符:不等于(<>或!=),<=,>=,不大于(!>或<=),不小于(!<或>=),BETWEEN,IS NULL

-- 查询价格不超过10美元的产品
SELECT prod_name,prod_price
FROM Products
WHERE prod_price<=10;
-- 查询所有不是供应商DLL01制造的产品-不匹配检查
SELECT prod_name,vend_id
FROM Products
WHERE vend_id != 'DLL01';  -- 字符串类型必须用''括起来     -- 不同的DBMS支持不同的操作符,比如不等于号不一定两种都支持

– 范围值(闭区间)检查 BETWEEN AND

-- 查询价格在5-10之间的所有产品,包括5和10
SELECT prod_name,prod_price
FROM Products
WHERE prod_price BETWEEN 5 AND 10;

– 空值检查,当一个单元格不包含值时,即包含空值NULL,什么也不包含,IS NULL,不能=NULL

-- 查询Customers表中电子邮件为空的顾客
SELECT cust_name
FROM Customers
WHERE cust_email IS NULL;

note:当查询不匹配某个值的结果时数据库是不会返回空值的行的,理论上空值也不算匹配,如果希望也返回空值,需要修改过滤条件 where A!=‘a’ or A is null

高级查询

– 高级数据过滤,组合WHERE子句
AND操作符,可以使用多个AND增加条件

-- 查询产品表中由供应商DLL01制造且价格不超过4的所有产品(名称+价格)
SELECT prod_name,prod_price
FROM Products
WHERE vend_id='DLL01' AND prod_price<=4;

OR操作符

-- 查询产品表中由供应商DLL01或BRS01制造的产品和价格
SELECT prod_name,prod_price
FROM Products
WHERE vend_id='DLL01' OR vend_id='BRS01';

– 由于在where子句中可以包含任意数目个AND,OR操作符,而and优先级高,因此使用括号避免不必要的优先级错误
– 任何时候都应该使用括号明确的分组操作符,消除歧义

-- 查询产品表中价格超过10,并且由供应商DLL01或BRS01制造的所有产品
SELECT prod_name,prod_price
FROM Products
WHERE prod_price>=10 AND (vend_id='DLL01' OR vend_id='BRS01');

IN操作符,‘属于’,取一组圆括号内由逗号分隔的值是范围,只要在范围中就可以匹配,功能与OR相当
– 一般比一组OR操作符执行的更快,语法更简洁,最大优点是可以包含其他SELECT语句,能更动态的建立WHERE子句

-- 查询由这两个供应商制造的产品
SELECT prod_name,prod_price
FROM Products
WHERE vend_id IN ('DLL01','BRS01');

– WHERE子句中的NOT操作符,否定其后跟的任何条件,可以用在要过滤的列前
– NOT + 条件:表示匹配除了这个条件以外的所有情况
– NOT IN :‘不属于,不在这个范围内’

-- 查询产品表中除这个供应商之外的其他所有供应商制造的产品
SELECT prod_name,prod_price
FROM Products
WHERE NOT vend_id ='DLL01';

通配符过滤,使用LIKE操作符告诉DBMS后面是通配符匹配

– 通配符:匹配值的一部分,只用于文本匹配,有%,_, [],匹配的文本要用‘’括起来
– 通配符可以在搜索模式的任意位置使用
– 搜索模式:由字面值、通配符或二者组合构成的搜索条件

通配符 %:表示任何字符出现任意次数,包括0次

-- 查询产品表中所有以Fish开头的产品名
SELECT prod_id,prod_name
FROM Products
WHERE prod_name LIKE 'fish%';  -- sqlserver在搜索模式下也不区分大小写
-- 查询产品名中含‘bean bag’的产品
SELECT prod_id,prod_name
FROM Products
WHERE prod_name LIKE '%bean bag%';  --注意两端不要有空格,否则也会匹配空格
-- 查询产品名中以F开头,以y结尾的产品,%在中间,对于搜索email地址很有用,例如:  WHERE email LIKE b%@163.com
SELECT prod_id,prod_name
FROM Products
WHERE prod_name LIKE 'F%y'; 

– note: 由于字段数据类型规定了长度,如果填不满DBMS默认以空格填充,那么在检索以某个字符结尾时就可能不对,方法是用函数去掉空格,sqlserver能匹配到
– % 虽然匹配任何字符,但不匹配NULL

下划线_ :匹配任意单个字符,不能多也不能少

-- 查询产品名中两位数英尺的泰迪熊
SELECT prod_id,prod_name
FROM Products
WHERE prod_name LIKE '__ inch teddy bear'; 

方括号[] 匹配符
– 指定一个字符集,在指定位置匹配该字符集中的任意一个字符

-- 查询顾客表中所有名字以J或M开头的联系人
SELECT cust_contact
FROM Customers
WHERE cust_contact LIKE '[JM]%'  -- 匹配以J或M开头的后面是任意字符的
ORDER BY cust_contact;

– 方括号内可以用 ^ 来否定,即匹配除了方括号内的内容,否定方括号内的这个集合,等同于NOT的使用,唯一优点是简化语法

-- 查询顾客表中所有名字不以J和M开头的联系人
SELECT cust_contact
FROM Customers
WHERE cust_contact LIKE '[^JM]%'  -- 匹配不以J和M开头的后面是任意字符的 ,等同于使用NOT, WHERE NOT cust_contact LIKE '[JM]%',也等同于WHERE cust_contact NOT LIKE '[JM]%' 
ORDER BY cust_contact;

note使用时要细心。不要使用过度,因为通配符搜索比其他搜索更慢,其他操作符能达到同样目的就不要用通配符。尽量不要把通配符放在搜索模式的开始处,这样搜索是最慢的。

拼接字段-输出结果的重新显示

当数据库直接存储的数据row data不是我们想要的格式时,需要直接从数据库中检索出经过转换、计算或格式化的数据,比在客户端快。
计算字段并不实际存在于表中,是运行语句时创建的。
从客户端APP来看,计算字段的数据与真实列的数据的返回方式相同。

拼接 :将多列的值合并成一个值,使用+号
-- 将供应商表的供应商名字和国家合为一列显示,国家放在括号中
SELECT RTRIM(vend_name)+' ('+RTRIM(vend_country)+')'
		AS vend_title                                    -- 最好指定别名,且最好是一个单词,不要是短语
FROM Vendors
ORDER BY vend_name;

– 由于国家是50个字符的字符串,因此包含空格才有右括号,并且返回的新构造的列,没有指定列名
– 解决方法:使用rtrim函数去掉值右边所有空格,LTRIM()去掉字符串左边的空格,TRIM()去掉字符串左右两边的空格
–由于未命名的新列不能被客户端引用,因此需要指定一个别名(alias),使用AS关键字
– 当实际的列名不合法或不合适想变更时,可以通过别名重命名
– 别名也称为导出列

算数计算
-- 查询订单详情表中订单号为20008中的所有物品,并计算每种物品的总价(数量*单价)作为‘扩展价格’列
SELECT prod_id,quantity,item_price,
	   quantity*item_price AS expanded_price      -- 客户端可以像使用实际列一样使用这个新计算列
FROM OrderItems
WHERE order_num=20008;

SELECT语句的作用:省略后面所有子句的话,select语句就可以测试、检验函数和计算,就是简单的访问处理表达式,只不过返回结果是一个新列

SELECT 3*2;
SELECT TRIM(' ABC ');

数据处理函数

– 每个DBMS都有特定的函数,SqlServer中,提取字符串的子串使用SUBSTRING();数据类型转换使用CONVERT();取当前日期使用GETDATE(),这使得函数不可移植
– 可移植:代码可以在不同的系统上运行
– 所以如果必须使用函数时要做好注释

1.文本处理函数

UPPER():将文本全部转换为大写

-- 查询供应商表的供应商名,并以大写显示,作为新列
SELECT vend_name,
	   UPPER(vend_name) AS vend_name_upcase
FROM Vendors
ORDER BY vend_name;

SOUNDEX():返回发音类似于输入参数的结果,如果数据拼错了能够检索出发音相似的正确的数据

-- 查询顾客表中联系名为‘Michael Green’或发音类似于改名的结果
SELECT cust_name,cust_contact
FROM Customers
WHERE SOUNDEX(cust_contact) = SOUNDEX('Michael Green');  -- 返回的是发音结果,该句查询两个发音相似的结果

在这里插入图片描述

2.日期时间处理函数,最重要,可移植性最差

DATEPART(返回的成分(yy:年,mm:月,dd:日),从哪里返回(要查询的日期)),返回符合的日期部分的值(年/月/日的值)

-- 查询订单表中2012年的所有订单,使用DATEPART()返回符合的日期部分的值(年/月/日的值)
SELECT order_num
FROM Orders
WHERE DATEPART(YY,order_date)=2012;
3.数值处理函数,使用最不频繁,不同DBMS中最一致

在这里插入图片描述

发布了24 篇原创文章 · 获赞 6 · 访问量 1188

猜你喜欢

转载自blog.csdn.net/wbing96/article/details/103103444