7.6 SQL Server条件查询

SQL Server条件查询

SQL Server WHERE

简介

使用SELECT语句对表查询数据时,一般来说不需要返回所有的数据行

条件查询是通过where子句进行检索的查询方式:

select 字段名1, 字段名2, …, 字段名n
from 数据表名
where 查询条件

WHERE子句中指定查询条件,只有满足查询条件的记录才会被返回。

查询条件是一个逻辑表达式或多个逻辑表达式的组合。

注意:SQL中,逻辑表达式的值可以是TRUE,FALSE,UNKNOWN(未知),查询只返回表达式值为TRUE的记录。

SQL Server WHERE示例

有如下产品表:

A)等值查询(=)

SELECT
    product_id,
    product_name,
    category_id,
    model_year,
    list_price
FROM
    production.products
WHERE
    category_id = 1
ORDER BY
    list_price DESC;

B)查找满足两个条件的行(AND)

使用AND组合条件

SELECT
    product_id,
    product_name,
    category_id,
    model_year,
    list_price
FROM
    production.products
WHERE
    category_id = 1 AND model_year = 2018
ORDER BY
    list_price DESC;

C)使用比较运算符查找(>,>=,<,<=,!=)

SELECT
    product_id,
    product_name,
    category_id,
    model_year,
    list_price
FROM
    production.products
WHERE
    list_price > 300 AND model_year = 2018
ORDER BY
    list_price DESC;

D)查找满足两个条件之一的行(OR)

使用OR组合条件

SELECT
    product_id,
    product_name,
    category_id,
    model_year,
    list_price
FROM
    production.products
WHERE
    list_price > 3000 OR model_year = 2018
ORDER BY
    list_price DESC;

E)查找值介于两个值之间的行(BETWEEN)

SELECT
    product_id,
    product_name,
    category_id,
    model_year,
    list_price
FROM
    production.products
WHERE
    list_price BETWEEN 1899.00 AND 1999.99
ORDER BY
    list_price DESC;

F)查询列具有在值列表中的值的行(IN)

SELECT
    product_id,
    product_name,
    category_id,
    model_year,
    list_price
FROM
    production.products
WHERE
    list_price IN (299.99, 369.99, 489.99)
ORDER BY
    list_price DESC;

G)查找值包含字符串的行(LIKE)

SELECT
    product_id,
    product_name,
    category_id,
    model_year,
    list_price
FROM
    production.products
WHERE
    list_price > 3000 OR model_year = 2018
ORDER BY
    list_price DESC;

SQL Server NULL

简介

在数据库世界中,NULL用于指示不存在任何数据值。例如,当记录客户信息时,电子邮件可能是未知的,在数据库中将其记录为NULL

通常,逻辑表达式的结果为TRUEFALSE。然而,当逻辑表达式中包含NULL时,结果是UNKNOWN。因此,逻辑表达式可能返回三值逻辑之一:TRUEFALSEUNKNOWN

以下比较结果为UNKNOWN

NULL = 0
NULL <> 0
NULL > 0
NULL = NULL

NULL不等于任何值,甚至不等于它本身。这意味着NULL不等于NULL,因为每个NULL可能不同。

IS NULL

有如下客户表:

以下语句查找没有在客户表中记录电话号码的客户,即phone列为null得客户:

SELECT
    customer_id,
    first_name,
    last_name,
    phone
FROM
    sales.customers
WHERE
    phone = NULL
ORDER BY
    first_name,
    last_name;

查询返回了空结果集。

WHERE子句返回条件表达式计算为TRUE的行。但是,以下表达式的计算结果为UNKNOWN:

phone = NULL;

所以返回了空结果集。

要测试值是否为空,使用IS NULL运算符。

SELECT
    customer_id,
    first_name,
    last_name,
    phone
FROM
    sales.customers
WHERE
    phone IS NULL
ORDER BY
    first_name,
    last_name;`

查询返回了没有电话信息的客户。

如果要检查一个值不为NULL,使用IS NOT NULL

以下查询返回具有电话信息的客户:

SELECT
    customer_id,
    first_name,
    last_name,
    phone
FROM
    sales.customers
WHERE
    phone IS NOT NULL
ORDER BY
    first_name,
    last_name;

SQL Server AND

AND简介

AND是一个逻辑运算符,允许您组合两个布尔表达式。只有当两个表达式的值都为TRUE时,它才会返回TRUE:

boolean_expression AND boolean_expression   

boolean_expression是任何有效的布尔表达式,其计算结果为TRUEFALSEUNKNOWN

下面是TRUE,FALSE,UNKNOWN通过AND不同组合的结果:

TRUE AND TRUE == TRUE
TRUE AND FALSE == FALSE
FALSE AND FALSE == FALSE
TRUE AND UNKNOWN == UNKNOWN
FALSE AND UNKNOWN == FALSE
UNKNOWN AND UNKNOWN == UNKNOWN

在表达式中使用多个逻辑运算符时,SQL Server始终首先计算AND运算符。但是,可以使用括号更改求值顺序。

AND运算符示例

有如下产品表:

A)使用单个AND
查找类别id为1且标价大于400的产品:

SELECT
    *
FROM
    production.products
WHERE
    category_id = 1
AND list_price > 400
ORDER BY
    list_price DESC;

B)使用多个AND
查找满足以下所有条件的产品:类别id为1,标价大于400,品牌id为1:

SELECT
    *
FROM
    production.products
WHERE
    category_id = 1
AND list_price > 400
AND brand_id = 1
ORDER BY
    list_price DESC;

C)使用AND和其他操作符

SELECT
    *
FROM
    production.products
WHERE
    brand_id = 1
OR brand_id = 2
AND list_price > 1000
ORDER BY
    brand_id DESC;

此例子中,使用了ANDOR操作符,SQL Server先处理AND操作符。然后处理OR操作符.

如果想先执行OR操作符得话:

SELECT
    *
FROM
    production.products
WHERE
    (brand_id = 1 OR brand_id = 2)
AND list_price > 1000
ORDER BY
    brand_id;

SQL Server OR

OR简介

SQL Server OR是一个逻辑运算符,允许您组合两个布尔表达式。当任一条件的计算结果为TRUE时,它将返回TRUE。

语法:

boolean_expression OR boolean_expression  

下面是TRUE,FALSE,UNKNOWN通过AND不同组合的结果:

TRUE OR TRUE == TRUE
TRUE OR FALSE == TRUE
FALSE OR FALSE == FALSE
TRUE OR UNKNOWN == TRUE
FALSE OR UNKNOWN == UNKNOWN
UNKNOWN OR UNKNOWN == UNKNOWN

OR示例:
A)查找标价低于200或高于6000的产品:

SELECT
    product_name,
    list_price
FROM
    production.products
WHERE
    list_price < 200
OR list_price > 6000
ORDER BY
    list_price;

查找品牌id为1、2或4的产品:

SELECT
    product_name,
    brand_id
FROM
    production.products
WHERE
    brand_id = 1
OR brand_id = 2
OR brand_id = 4
ORDER BY
    brand_id DESC;

可以用IN运算符替换多个OR运算符,如以下查询所示:

SELECT
    product_name,
    brand_id
FROM
    production.products
WHERE
    brand_id IN (1, 2, 3)
ORDER BY
    brand_id DESC;

SQL Server IN

简介

IN运算符是一个逻辑运算符,允许您测试指定值是否与列表中的任何值匹配。

语法:

column | expression IN ( v1, v2, v3, ...)
  • 首先,指定列或表达式。
  • 其次,指定值列表。所有值的类型必须与列或表达式的类型相同。

如果列或表达式中的值等于列表中的任何值,则IN运算符的结果为TRUE。

IN运算符等价于多个OR运算符,因此,下面是等价的:

column IN (v1, v2, v3)

column = v1 OR column = v2 OR column = v3

要否定IN运算符,使用NOT IN运算符,如下所示:

column | expression NOT IN ( v1, v2, v3, ...)

除了值列表之外,还可以使用子查询,该子查询返回值列表供IN运算符使用,如下所示:

column | expression IN (subquery)

在这种语法中,子查询是一个SELECT语句,返回单个列的值列表。

请注意,如果列表包含NULL,则INNOT IN的结果将是UNKNOWN:

示例

有如下产品表:

A)SQL Server IN与值列表示例
查找标价为以下值之一的产品:89.99、109.99和159.99:

SELECT
    product_name,
    list_price
FROM
    production.products
WHERE
    list_price IN (89.99, 109.99, 159.99)
ORDER BY
    list_price;

上述查询相当于以下使用OR运算符的查询:

SELECT
    product_name,
    list_price
FROM
    production.products
WHERE
    list_price = 89.99 OR list_price = 109.99 OR list_price = 159.99
ORDER BY
    list_price;

要查找其标价不是上述价格之一的产品,请使用NOT IN运算符,如以下查询所示:

SELECT
    product_name,
    list_price
FROM
    production.products
WHERE
    list_price NOT IN (89.99, 109.99, 159.99)
ORDER BY
    list_price;

B)SQL Server IN与子查询示例

SELECT
    product_name,
    list_price
FROM
    production.products
WHERE
    product_id IN (
        SELECT
            product_id
        FROM
            production.stocks
        WHERE
            store_id = 1 AND quantity >= 30
    )
ORDER BY
    product_name;
  • 首先,子查询返回产品id列表。
  • 其次,外部查询检索产品id与子查询返回的任何值匹配的产品。

SQL Server between

BETWEEN简介

逻辑运算符BETWEEN,允许指定要查询的范围:

column | expression BETWEEN start_expression AND end_expression

查询返回指定列column或表达式expression得值大于等于start_expression并且小于等于end_expression得记录。

也可以使用>=<=进行替换:

column | expression <= end_expression AND column | expression >= start_expression 

要否定BETWEEN运算符的结果,使用NOT BETWEEN操作符,如下所示:

column | expression NOT BETWEEN start_expression AND end_expresion

同理可以使用<>替换:

column | expression < start_expression AND column | expression > end_expression

注意,如果对BETWEENNOT BETWEEN的任何输入为NULL,则结果是UNKNOWN

BETWEEN示例

A)BETWEEN与数字类型

有如下产品表:

1)查找标价在149.99和199.99之间的产品:

SELECT
    product_id,
    product_name,
    list_price
FROM
    production.products
WHERE
    list_price BETWEEN 149.99 AND 199.99
ORDER BY
    list_price;

2)查询标价不在149.99和199.99之间的产品,请使用NOT BETWEEN运算符,如下所示:

SELECT
    product_id,
    product_name,
    list_price
FROM
    production.products
WHERE
    list_price NOT BETWEEN 149.99 AND 199.99
ORDER BY
    list_price;

B)BETWEEN与日期类型

有如下订单表:

以下查询将查找客户在2017年1月15日至17日之间下的订单:

SELECT
    order_id,
    customer_id,
    order_date,
    order_status
FROM
    sales.orders
WHERE
    order_date BETWEEN '20170115' AND '20170117'
ORDER BY
    order_date;

请注意,要指定字符串格式的日期,请使用YYYYMMDD格式,其中YYYY是4位数字的年份,例如2017年,MM是2位数字的月份,例如01,DD是两位数字的天,例如15。

SQL Server LIKE

简介

SQL Server 逻辑运算符LILE用于确定字符串是否与指定模式匹配。
模式可以包括常规字符和通配符。在SELECTUPDATEDELETE语句的WHERE子句中使用LIKE运算符来基于模式匹配筛选行。

语法:

column | expression LIKE pattern [ESCAPE escape_character]

Pattern

模式是要在列或表达式中搜索的字符序列。它可以包括以下有效通配符:

  • 百分比通配符(%):零个或多个字符的任何字符串。
  • 下划线通配符(_):任何单个字符。
  • [字符列表]通配符:指定集合中的任何单个字符。
  • [字符-字符]:指定范围内的任何单个字符。
  • [^]:不在列表或范围内的任何单个字符。

通配符使LIKE运算符比相等(=)和不相等(!=)的字符串更灵活。

Escape character(转义字符)

转义字符指定LIKE运算符将通配符视为常规字符。转义字符没有默认值,只能计算为一个字符。

如果列或表达式与指定的模式匹配,则LIKE运算符返回TRUE

要否定LIKE运算符的结果,请按如下方式使用NOT运算符:

column | expression NOT LIKE pattern [ESCAPE escape_character]

LIKE示例

有如下客户表:

(百分比)通配符示例

以下示例查找姓氏以字母z开头的客户:

SELECT
    customer_id,
    first_name,
    last_name
FROM
    sales.customers
WHERE
    last_name LIKE 'z%'
ORDER BY
    first_name;

以下示例返回姓氏以字符串er结尾的客户:

SELECT
    customer_id,
    first_name,
    last_name
FROM
    sales.customers
WHERE
    last_name LIKE '%er'
ORDER BY
    first_name;

以下语句检索姓氏以字母t开头,以字母s结尾的客户:

SELECT
    customer_id,
    first_name,
    last_name
FROM
    sales.customers
WHERE
    last_name LIKE 't%s'
ORDER BY
    first_name;

_(下划线)通配符示例

下划线表示单个字符。例如,以下语句返回第二个字符为字母u的客户:

SELECT
    customer_id,
    first_name,
    last_name
FROM
    sales.customers
WHERE
    last_name LIKE '_u%'
ORDER BY
    first_name; 

通配符 _u%:

  • 第一个下划线字符(_)匹配任何单个字符。
  • 第二个字母u与字母u完全匹配
  • 第三个字符%匹配任何字符序列

[字符列表]通配符示例

带有字符列表的方括号,例如[ABC]表示一个字符,该字符必须是列表中指定的字符之一。

例如,以下查询返回姓氏中第一个字符为YZ的客户:

SELECT
    customer_id,
    first_name,
    last_name
FROM
    sales.customers
WHERE
    last_name LIKE '[YZ]%'
ORDER BY
    last_name;

[字符-字符]通配符示例

带有字符范围的方括号,例如[A-C],表示必须在指定范围内的单个字符。

例如,以下查询查找姓氏中的第一个字符是A到C范围内的字母的客户:

SELECT
    customer_id,
    first_name,
    last_name
FROM
    sales.customers
WHERE
    last_name LIKE '[A-C]%'
ORDER BY
    first_name;

[^字符列表或范围]通配符示例

带有插入符号(^)的方括号后跟一个范围,例如[^A-C]或[^ABC],表示不在指定范围或字符列表中的单个字符。

例如,以下查询返回姓氏中的第一个字符不是A到X范围内的字母的客户:

SELECT
    customer_id,
    first_name,
    last_name
FROM
    sales.customers
WHERE
    last_name LIKE '[^A-X]%'
ORDER BY
    last_name;

NOT LIKE示例

以下示例使用NOT LIKE运算符查找名字中第一个字符不是字母A的客户:

SELECT
    customer_id,
    first_name,
    last_name
FROM
    sales.customers
WHERE
    first_name NOT LIKE 'A%'
ORDER BY
    first_name;

LIKE与转义字符示例

首先,为演示创建一个新(反馈)表:

CREATE TABLE sales.feedbacks (
   feedback_id INT IDENTITY(1, 1) PRIMARY KEY, 
    comment     VARCHAR(255) NOT NULL
);

第二,在反馈表中插入一些行:

INSERT INTO sales.feedbacks(comment)
VALUES('Can you give me 30% discount?'),
      ('May I get me 30USD off?'),
      ('Is this having 20% discount today?');

第三,查询一下:

SELECT * FROM sales.feedbacks;

如果您想在“评论”列中搜索30%,您可能会得到如下查询:

SELECT 
   feedback_id,
   comment
FROM 
   sales.feedbacks
WHERE 
   comment LIKE '%30%';

查询返回包含30%30USD的评论,这不是我们期望的。

要解决此问题,您需要使用ESCAPE子句:

SELECT 
   feedback_id, 
   comment
FROM 
   sales.feedbacks
WHERE 
   comment LIKE '%30!%%' ESCAPE '!';

在该查询中,ESCAPE子句指定字符是转义字符。它指示LIKE%字符视为文字字符串,而不是通配符。注意,如果没有ESCAPE子句,查询将返回空结果集。

SQL Server别名

列别名

使用SELECT语句查询表中的数据时,SQL Server将列名用作输出的列标题。请参见以下示例:

SELECT
    first_name,
    last_name
FROM
    sales.customers
ORDER BY
    first_name;

如输出所示,first_namelast_name列名分别用于列标题。

要获取客户的全名,可以使用+运算符连接名字、空格和姓氏,如以下查询所示:

SELECT
    first_name + ' ' + last_name
FROM
    sales.customers
ORDER BY
    first_name;

SQL Server将全名列返回为No column name(无列名),这在本例中没有意义。

要在查询执行期间为列或表达式指定临时名称,可以使用别名。

column_name | expression  AS column_alias

在此语法中,使用AS关键字分隔列名或表达式和别名。

AS关键字是可选的,因此可以按如下方式为列分配别名:

column_name | expression column_alias

回到上面的示例,您可以使用列别名重写查询:

SELECT
    first_name + ' ' + last_name AS full_name
FROM
    sales.customers
ORDER BY
    first_name;

注意,如果列别名包含空格,则需要将其括在引号中,如以下示例所示

SELECT
    first_name + ' ' + last_name AS 'Full Name'
FROM
    sales.customers
ORDER BY
    first_name;

以下示例显示了如何为列分配别名:

SELECT
    category_name 'Product Category'
FROM
    production.categories;

为列指定别名后,可以在ORDER BY子句中使用列名或列别名,如以下示例所示:

SELECT
    category_name 'Product Category'
FROM
    production.categories
ORDER BY
    category_name;  


SELECT
    category_name 'Product Category'
FROM
    production.categories
ORDER BY
    'Product Category';

注意,ORDER BY子句是最后一个要处理的子句,因此列别名在ORDER BY时是已知的。

表别名

与列别名类似,可以使用或不使用AS关键字分配表别名:

table_name AS table_alias
table_name table_alias

请参见以下示例:

SELECT
    sales.customers.customer_id,
    first_name,
    last_name,
    order_id
FROM
    sales.customers
INNER JOIN sales.orders ON sales.orders.customer_id = sales.customers.customer_id;

在本例中,customersorders表都有一个名为customer_id的列,因此,需要使用以下语法引用该列:

table_name.column_name

比如:

sales.custoners.customer_id
sales.orders.customer_id

如果直接写字段名的话就会报错。

上面的查询可读性很差。但是,可以通过使用表别名来提高可读性,如下所示:

SELECT
    c.customer_id,
    first_name,
    last_name,
    order_id
FROM
    sales.customers c
INNER JOIN sales.orders o ON o.customer_id = c.customer_id;

这个例子中C是客户表的别名,o是订单表的别名。

为表分配别名后,必须使用别名引用表列。否则,SQL Server将报错。

posted @ 2022-08-27 22:42  平元兄  阅读(622)  评论(0编辑  收藏  举报