谓词

什么是谓词

谓词就是返回值为真值的函数。包括TRUE / FALSE / UNKNOWN

谓词主要有以下几个:

  • LIKE
  • BETWEEN
  • IS NULL、IS NOT NULL
  • IN
  • EXISTS

LIKE谓词 – 用于字符串的部分一致查询

当需要进行字符串的部分一致查询时需要使用该谓词。

部分一致大体可以分为前方一致、中间一致和后方一致三种类型。

前方一致:'ddd%'

中间一致:'%ddd%'

中间一致:'%ddd'

_下划线匹配任意 1 个字符

BETWEEN谓词 – 用于范围查询

使用 BETWEEN 可以进行范围查询。该谓词与其他谓词或者函数的不同之处在于它使用了 3 个参数,between x and y。且都是闭区间。

如果不想让结果中包含临界值,那就必须使用 < 和 >。

IS NULL、 IS NOT NULL – 用于判断是否为NULL

为了选取出某些值为 NULL 的列的数据,不能使用 =,而只能使用特定的谓词IS NULL。与此相反,想要选取 NULL 以外的数据时,需要使用IS NOT NULL。

IN谓词 – OR的简便用法

多个查询条件取并集时可以选择使用or语句,可以使用否定形式NOT IN来取反,使用IN 和 NOT IN 时是无法选取出NULL数据的。

使用子查询作为IN谓词的参数

  • IN和子查询

IN 谓词(NOT IN 谓词)具有其他谓词所没有的用法,那就是可以使用子查询作为其参数。子查询就是 SQL内部生成的表,因此也可以说“能够将表作为 IN 的参数”。同理,我们还可以说“能够将视图作为 IN 的参数”。

EXIST 谓词

  • EXIST谓词的使用方法

谓词的作用就是 “判断是否存在满足某种条件的记录”

如果存在这样的记录就返回真(TRUE),如果不存在就返回假(FALSE)。

EXIST(存在)谓词的主语是“记录”。

  • EXIST的参数

之前我们学过的谓词,基本上都是像“列 LIKE 字符串”或者“ 列 BETWEEN 值 1 AND 值 2”这样需要指定 2 个以上的参数,而 EXIST 的左侧并没有任何参数。因为 EXIST 是只有 1 个参数的谓词。 所以,EXIST 只需要在右侧书写 1 个参数,该参数通常都会是一个子查询。

  • 使用NOT EXIST替换NOT IN

就像 EXIST 可以用来替换 IN 一样, NOT IN 也可以用NOT EXIST来替换。

NOT EXIST 与 EXIST 相反,当“不存在”满足子查询中指定条件的记录时返回真(TRUE)。

CASE 表达式

语法:

CASE WHEN <求值表达式> THEN <表达式>
     WHEN <求值表达式> THEN <表达式>
     WHEN <求值表达式> THEN <表达式>
     .
     .
     .
ELSE <表达式>
END

上述语句执行时,依次判断 when 表达式是否为真值,是则执行 THEN 后的语句,如果所有的 when 表达式均为假,则执行 ELSE 后的语句。
无论多么庞大的 CASE 表达式,最后也只会返回一个值。

假设现在 要实现如下结果:

A :衣服
B :办公用品
C :厨房用具  

因为表中的记录并不包含“A : ”或者“B : ”这样的字符串,所以需要在 SQL 中进行添加。并将“A : ”“B : ”“C : ”与记录结合起来。

  • 应用场景1:根据不同分支得到不同列值
SELECT  product_name,
        CASE WHEN product_type = '衣服' THEN CONCAT('A : ',product_type)
             WHEN product_type = '办公用品'  THEN CONCAT('B : ',product_type)
             WHEN product_type = '厨房用具'  THEN CONCAT('C : ',product_type)
             ELSE NULL
        END AS abc_product_type
  FROM  product;
+--------------+------------------+
| product_name | abc_product_type |
+--------------+------------------+
| T恤          | A : 衣服        |
| 打孔器       | B : 办公用品    |
| 运动T恤      | A : 衣服        |
| 菜刀         | C : 厨房用具    |
| 高压锅       | C : 厨房用具    |
| 叉子         | C : 厨房用具    |
| 擦菜板       | C : 厨房用具    |
| 圆珠笔       | B : 办公用品    |
+--------------+------------------+
8 rows in set (0.00 sec)

ELSE 子句也可以省略不写,这时会被默认为 ELSE NULL。但为了防止有人漏读,还是希望大家能够显示地写出 ELSE 子句。
此外, CASE 表达式最后的“END”是不能省略的,请大家特别注意不要遗漏。忘记书写 END 会发生语法错误,这也是初学时最容易犯的错误。

  • 应用场景2:实现列方向上的聚合

通常我们使用如下代码实现行的方向上不同种类的聚合(这里是 sum)

SELECT product_type,
       SUM(sale_price) AS sum_price
  FROM product
 GROUP BY product_type;  
+--------------+-----------+
| product_type | sum_price |
+--------------+-----------+
| 衣服         |      5000 |
| 办公用品      |       600 |
| 厨房用具      |     11180 |
+--------------+-----------+
3 rows in set (0.00 sec)

假如要在列的方向上展示不同种类额聚合值,该如何写呢?

sum_price_clothes | sum_price_kitchen | sum_price_office
------------------+-------------------+-----------------
             5000 |             11180 |              600  

聚合函数 + CASE WHEN 表达式即可实现该效果

-- 对按照商品种类计算出的销售单价合计值进行行列转换
SELECT SUM(CASE WHEN product_type = '衣服' THEN sale_price ELSE 0 END) AS sum_price_clothes,
       SUM(CASE WHEN product_type = '厨房用具' THEN sale_price ELSE 0 END) AS sum_price_kitchen,
       SUM(CASE WHEN product_type = '办公用品' THEN sale_price ELSE 0 END) AS sum_price_office
  FROM product;
+-------------------+-------------------+------------------+
| sum_price_clothes | sum_price_kitchen | sum_price_office |
+-------------------+-------------------+------------------+
|              5000 |             11180 |              600 |
+-------------------+-------------------+------------------+
1 row in set (0.00 sec)
  • (扩展内容)应用场景3:实现行转列

假设有如下图表的结构

图片

计划得到如下的图表结构

图片

聚合函数 + CASE WHEN 表达式即可实现该转换

-- CASE WHEN 实现数字列 score 行转列
SELECT name,
       SUM(CASE WHEN subject = '语文' THEN score ELSE null END) as chinese,
       SUM(CASE WHEN subject = '数学' THEN score ELSE null END) as math,
       SUM(CASE WHEN subject = '外语' THEN score ELSE null END) as english
  FROM score
 GROUP BY name;
+------+---------+------+---------+
| name | chinese | math | english |
+------+---------+------+---------+
| 张三 |      93 |   88 |      91 |
| 李四 |      87 |   90 |      77 |
+------+---------+------+---------+
2 rows in set (0.00 sec)

上述代码实现了数字列 score 的行转列,也可以实现文本列 subject 的行转列

-- CASE WHEN 实现文本列 subject 行转列
SELECT name,
       MAX(CASE WHEN subject = '语文' THEN subject ELSE null END) as chinese,
       MAX(CASE WHEN subject = '数学' THEN subject ELSE null END) as math,
       MIN(CASE WHEN subject = '外语' THEN subject ELSE null END) as english
  FROM score
 GROUP BY name;
+------+---------+------+---------+
| name | chinese | math | english |
+------+---------+------+---------+
| 张三 | 语文    | 数学 | 外语    |
| 李四 | 语文    | 数学 | 外语    |
+------+---------+------+---------+
2 rows in set (0.00 sec

总结:

  • 当待转换列为数字时,可以使用SUM AVG MAX MIN等聚合函数;
  • 当待转换列为文本时,可以使用MAX MIN等聚合函数

 

 

 

 

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐