openGauss学习笔记-17 openGauss 简单数据管理-表达式

openGauss学习笔记-17 openGauss 简单数据管理-表达式17.1 简单表达式17.2 条件表达式17.3 子查询表达式17.4 数组表达式17.5 行表达式

openGauss学习笔记-17 openGauss 简单数据管理-表达式

表达式类似一个公式,我们可以将其应用在查询语句中,用来查找数据库中指定条件的结果集。

17.1 简单表达式

  • 逻辑表达式

    逻辑表达式的操作符和运算规则,详情请参见逻辑操作符

  • 比较表达式

    常用的比较操作符,请参见操作符

    除比较操作符外,还可以使用以下句式结构:

    • BETWEEN操作符

      a BETWEEN x AND y等效于a >= x AND a <= y

      a NOT BETWEEN x AND y等效于a < x OR a > y

    • 检查一个值是不是NULL,可使用:

      expression IS NULL

      expression IS NOT NULL

      或者与之等价的句式结构,但不是标准的:

      expression ISNULL

      expression NOTNULL

      须知: 不要写expression=NULL或expression<>(!=)NULL,因为NULL代表一个未知的值,不能通过该表达式判断两个未知值是否相等。

  • is distinct from/is not distinct from

    • is distinct from

      A和B的数据类型、值不完全相同时为true。

      A和B的数据类型、值完全相同时为false。

      将空值视为相同。

    • is not distinct from

      A和B的数据类型、值不完全相同时为false。

      A和B的数据类型、值完全相同时为true。

      将空值视为相同。

  • 伪列(ROWNUM)

    ROWNUM是一个伪列,它返回一个数字,表示从查询中获取结果的行编号。第一行的ROWNUM为1,第二行的为2,依此类推。ROWNUM的返回类型为numeric。ROWNUM可以用于限制查询返回的总行数,例如下面语句限制查询从customer_t1表中返回最多3条记录。

openGauss=# SELECT * FROM customer_t1 WHERE ROWNUM <= 3;
     c_customer_sk | c_customer_id | c_first_name | c_last_name | amount
    ---------------+---------------+--------------+-------------+--------
     3869 | hello         | Grace        |             |   1000
     3869 | hello         | Grace        |             |   1000
     3869 |               | Grace        |             |
    (3 rows)

17.2 条件表达式

在执行SQL语句时,可通过条件表达式筛选出符合条件的数据。

条件表达式主要有以下几种:

  • CASE

    CASE表达式是条件表达式,类似于其他编程语言中的CASE语句。

    CASE表达式的语法图请参考图1

    图 1

    [图片上传失败...(image-c5784f-1689988072514)]

    CASE子句可以用于合法的表达式中。condition是一个返回BOOLEAN数据类型的表达式:

    • 如果结果为真,CASE表达式的结果就是符合该条件所对应的result。

    • 如果结果为假,则以相同方式处理随后的WHEN或ELSE子句。

    • 如果各WHEN condition都不为真,表达式的结果就是在ELSE子句执行的result。如果省略了ELSE子句且没有匹配的条件,结果为NULL。

    示例:

    注:如果模式tpcds不存在。请创建模式tpcds后,再进行建表操作。

openGauss=# CREATE TABLE tpcds.case_when_t1(CW_COL1 INT);
    
    openGauss=# INSERT INTO tpcds.case_when_t1 VALUES (1), (2), (3);
    
    openGauss=# SELECT * FROM tpcds.case_when_t1;
    cw_col1 
    ---------
     1
     2
     3
    (3 rows)
    
    openGauss=# SELECT CW_COL1, CASE WHEN CW_COL1=1 THEN 'one' WHEN CW_COL1=2 THEN 'two' ELSE 'other' END FROM tpcds.case_when_t1 ORDER BY 1;
     cw_col1 | case
    ---------+-------
     1 | one
     2 | two
     3 | other
    (3 rows)
    
    openGauss=# DROP TABLE tpcds.case_when_t1;
  • DECODE

    DECODE的语法图请参见图2

    图 2 [图片上传失败...(image-f6748e-1689988072514)]

    将表达式base_expr与后面的每个compare(n) 进行比较,如果匹配返回相应的value(n)。如果没有发生匹配,则返回default。

    示例:

openGauss=# SELECT DECODE('A','A',1,'B',2,0);
     case 
    ------
     1
    (1 row)
  • COALESCE

    COALESCE的语法图请参见图3

    图 3 [图片上传失败...(image-ccd34d-1689988072514)]

    COALESCE返回它的第一个非NULL的参数值。如果参数都为NULL,则返回NULL。它常用于在显示数据时用缺省值替换NULL。和CASE表达式一样,COALESCE只计算用来判断结果的参数,即在第一个非空参数右边的参数不会被计算。

    示例:

    注:如果模式tpcds不存在。请创建模式tpcds后,再进行建表操作。

openGauss=# CREATE TABLE tpcds.c_tabl(AboutopenGauss varchar(10), short_AboutopenGauss varchar(10), last_value varchar(10)) ;
    
    openGauss=# INSERT INTO tpcds.c_tabl VALUES('abc', 'efg', '123');
    openGauss=# INSERT INTO tpcds.c_tabl VALUES(NULL, 'efg', '123');
    
    openGauss=# INSERT INTO tpcds.c_tabl VALUES(NULL, NULL, '123');
    
    openGauss=# SELECT AboutopenGauss, short_AboutopenGauss, last_value, COALESCE(AboutopenGauss, short_AboutopenGauss, last_value) FROM tpcds.c_tabl ORDER BY 1, 2, 3, 4;
     AboutopenGauss | short_AboutopenGauss | last_value | coalesce
    -------------+-------------------+------------+----------
     abc         | efg               | 123        | abc
     | efg               | 123        | efg
     |                   | 123        | 123
    (3 rows)
    
    openGauss=# DROP TABLE tpcds.c_tabl;
如果AboutopenGauss不为NULL,则返回AboutopenGauss的值,否则计算下一个参数short_AboutopenGauss;如果short_AboutopenGauss不为NULL,则返回short_AboutopenGauss的值,否则计算下一个参数last_value;如果last_value不为NULL,则返回last_value的值,否则返回(none)。
openGauss=# SELECT COALESCE(NULL,'Hello World');
     coalesce
    ---------------
     Hello World
    (1 row)
  • NULLIF

    NULLIF的语法图请参见图4

    图 4 [图片上传失败...(image-5c7213-1689988072514)]

    只有当value1和value2相等时,NULLIF才返回NULL。否则它返回value1。

    示例:

    注:如果模式tpcds不存在。请创建模式tpcds后,再进行建表操作。

openGauss=# CREATE TABLE tpcds.null_if_t1 (
     NI_VALUE1 VARCHAR(10),
     NI_VALUE2 VARCHAR(10)
    );
    
    openGauss=# INSERT INTO tpcds.null_if_t1 VALUES('abc', 'abc');
    openGauss=# INSERT INTO tpcds.null_if_t1 VALUES('abc', 'efg');
    
    openGauss=# SELECT NI_VALUE1, NI_VALUE2, NULLIF(NI_VALUE1, NI_VALUE2) FROM tpcds.null_if_t1 ORDER BY 1, 2, 3;
    
     ni_value1 | ni_value2 | nullif 
    -----------+-----------+--------
     abc       | abc       | 
     abc       | efg       | abc
    (2 rows)
    openGauss=# DROP TABLE tpcds.null_if_t1;
如果value1等于value2则返回NULL,否则返回value1。
openGauss=# SELECT NULLIF('Hello','Hello World');
     nullif 
    --------
     Hello
    (1 row)
  • GREATEST(最大值),LEAST(最小值)

    GREATEST的语法图请参见图5

    图 5 [图片上传失败...(image-4cd808-1689988072514)]

    从一个任意数字表达式的列表里选取最大的数值。

openGauss=# SELECT greatest(9000,155555,2.01);
     greatest 
    ----------
     155555
    (1 row)
LEAST的语法图请参见**图6**。

**图 6**  [图片上传失败...(image-e99aac-1689988072514)] 

从一个任意数字表达式的列表里选取最小的数值。

以上的数字表达式必须都可以转换成一个普通的数据类型,该数据类型将是结果类型。

列表中的NULL值将被忽略。只有所有表达式的结果都是NULL的时候,结果才是NULL。

示例:
openGauss=# SELECT least(9000,2);
     least 
    -------
     2
    (1 row)
  • NVL

    NVL的语法图请参见图7

    图 7 [图片上传失败...(image-a8a6d7-1689988072514)]

    如果value1为NULL则返回value2,如果value1非NULL,则返回value1。

    示例:

openGauss=# SELECT nvl(null,1);
    nvl 
    -----
     1
    (1 row)
    
    openGauss=# SELECT nvl ('Hello World' ,1);
     nvl
    ---------------
     Hello World
    (1 row)

17.3 子查询表达式

子查询表达式主要有以下几种:

  • EXISTS/NOT EXISTS

    EXISTS/NOT EXISTS的语法图请参见图8

    图 8 [图片上传失败...(image-693392-1689988072513)]

    EXISTS的参数是一个任意的SELECT语句,或者说子查询。系统对子查询进行运算以判断它是否返回行。如果它至少返回一行,则EXISTS结果就为"真";如果子查询没有返回任何行, EXISTS的结果是"假"。

    这个子查询通常只是运行到能判断它是否可以生成至少一行为止,而不是等到全部结束。

    示例:

    注:下面查询语句中tpcds是模式名。

openGauss=# SELECT sr_reason_sk,sr_customer_sk FROM tpcds.store_returns WHERE EXISTS (SELECT d_dom FROM tpcds.date_dim WHERE d_dom = store_returns.sr_reason_sk and sr_customer_sk <10);
    sr_reason_sk | sr_customer_sk 
    --------------+----------------
     13 |              2
     22 |              5
     17 |              7
     25 |              7
     3 |              7
     31 |              5
     7 |              7
     14 |              6
     20 |              4
     5 |              6
     10 |              3
     1 |              5
     15 |              2
     4 |              1
     26 |              3
    (15 rows)
  • IN/NOT IN

    IN/NOT IN的语法请参见图9

    图 9 [图片上传失败...(image-72a063-1689988072513)]

    右边是一个圆括弧括起来的子查询,它必须只返回一个字段。左边表达式对子查询结果的每一行进行一次计算和比较。如果找到任何相等的子查询行,则IN结果为"真"。如果没有找到任何相等行,则结果为"假"(包括子查询没有返回任何行的情况)。

    表达式或子查询行里的NULL遵照SQL处理布尔值和NULL组合时的规则。如果两个行对应的字段都相等且非空,则这两行相等;如果任意对应字段不等且非空,则这两行不等;否则结果是未知(NULL)。如果每一行的结果都是不等或NULL ,并且至少有一个NULL ,则IN的结果是NULL 。

    示例:

    注:下面查询语句中tpcds是模式名。

openGauss=# SELECT sr_reason_sk,sr_customer_sk  FROM tpcds.store_returns WHERE sr_customer_sk IN (SELECT d_dom FROM tpcds.date_dim WHERE d_dom < 10);
    sr_reason_sk | sr_customer_sk 
    --------------+----------------
     10 |              3
     26 |              3
     22 |              5
     31 |              5
     1 |              5
     32 |              5
     32 |              5
     4 |              1
     15 |              2
     13 |              2
     33 |              4
     20 |              4
     33 |              8
     5 |              6
     14 |              6
     17 |              7
     3 |              7
     25 |              7
     7 |              7
    (19 rows)
  • ANY/SOME

    ANY/SOME的语法图请参见图10

    图 10 any/some::= [图片上传失败...(image-317dc-1689988072513)]

    右边是一个圆括弧括起来的子查询,它必须只返回一个字段。左边表达式使用operator对子查询结果的每一行进行一次计算和比较,其结果必须是布尔值。如果至少获得一个真值,则ANY结果为“真”。如果全部获得假值,则结果是“假”(包括子查询没有返回任何行的情况)。SOME是ANY的同义词。IN与ANY可以等效替换 。

    示例:

    注:下面查询语句中tpcds是模式名。

openGauss=# SELECT sr_reason_sk,sr_customer_sk  FROM tpcds.store_returns WHERE sr_customer_sk < ANY (SELECT d_dom FROM tpcds.date_dim WHERE d_dom < 10);
    sr_reason_sk | sr_customer_sk 
    --------------+----------------
     26 |              3
     17 |              7
     32 |              5
     32 |              5
     13 |              2
     31 |              5
     25 |              7
     5 |              6
     7 |              7
     10 |              3
     1 |              5
     14 |              6
     4 |              1
     3 |              7
     22 |              5
     33 |              4
     20 |              4
     33 |              8
     15 |              2
    (19 rows)
  • ALL

    ALL的语法请参见图11

    图 11 [图片上传失败...(image-8602f2-1689988072513)]

    右边是一个圆括弧括起来的子查询,它必须只返回一个字段。左边表达式使用operator对子查询结果的每一行进行一次计算和比较,其结果必须是布尔值。如果全部获得真值,ALL结果为"真"(包括子查询没有返回任何行的情况)。如果至少获得一个假值,则结果是"假"。

    示例:

    注:下面查询语句中tpcds是模式名。

openGauss=# SELECT sr_reason_sk,sr_customer_sk  FROM tpcds.store_returns WHERE sr_customer_sk < all(SELECT d_dom FROM tpcds.date_dim WHERE d_dom < 10);
     sr_reason_sk | sr_customer_sk 
    --------------+----------------
    (0 rows)

17.4 数组表达式

  • IN

    expression IN (value [, …])

    右侧括号中的是一个表达式列表。左侧表达式的结果与表达式列表的内容进行比较。如果列表中的内容符合左侧表达式的结果,则IN的结果为true。如果没有相符的结果,则IN的结果为false。

    示例:

openGauss=# SELECT 8000+500 IN (10000, 9000) AS RESULT;
     result 
    ----------
     f
    (1 row)
如果表达式结果为null,或者表达式列表不符合表达式的条件且右侧表达式列表返回结果至少一处为空,则IN的返回结果为null,而不是false。这样的处理方式和SQL返回空值的布尔组合规则是一致的。
  • NOT IN

    expression NOT IN (value [, …])

    右侧括号中的是一个表达式列表。左侧表达式的结果与表达式列表的内容进行比较。如果在列表中的内容没有符合左侧表达式结果的内容,则NOT IN的结果为true。如果有符合的内容,则NOT IN的结果为false。

    示例:

openGauss=# SELECT 8000+500 NOT IN (10000, 9000) AS RESULT;
     result 
    ----------
     t
    (1 row)
如果查询语句返回结果为空,或者表达式列表不符合表达式的条件且右侧表达式列表返回结果至少一处为空,则NOT IN的返回结果为null,而不是false。这样的处理方式和SQL返回空值的布尔组合规则是一致的。

> **说明:** 在所有情况下X NOT IN Y等价于NOT(X IN Y)。
  • ANY/SOME(array)

    expression operator ANY (array expression)

    expression operator SOME (array expression)

    右侧括号中的是一个数组表达式,它必须产生一个数组值。左侧表达式的结果使用操作符对数组表达式的每一行结果都进行计算和比较,比较结果必须是布尔值。

    • 如果对比结果至少获取一个真值,则ANY的结果为true。

    • 如果对比结果没有真值,则ANY的结果为false。

    • 如果结果没有真值,并且数组表达式生成至少一个值为null,则ANY的值为NULL,而不是false。这样的处理方式和SQL返回空值的布尔组合规则是一致的。

    • SOME是ANY的同义词。

    示例:

openGauss=# SELECT 8000+500 < SOME (array[10000,9000]) AS RESULT;
     result 
    ----------
     t
    (1 row)
    
    openGauss=# SELECT 8000+500 < ANY (array[10000,9000]) AS RESULT;
     result 
    ----------
     t
    (1 row)
  • ALL(array)

    expression operator ALL (array expression)

    右侧括号中的是一个数组表达式,它必须产生一个数组值。左侧表达式的结果使用操作符对数组表达式的每一行结果都进行计算和比较,比较结果必须是布尔值。

    • 如果所有的比较结果都为真值(包括数组不含任何元素的情况),则ALL的结果为true。

    • 如果存在一个或多个比较结果为假值,则ALL的结果为false。

    • 如果数组表达式产生一个NULL数组,则ALL的结果为NULL。如果左边表达式的值为NULL ,则ALL的结果通常也为NULL(某些不严格的比较操作符可能得到不同的结果)。另外,如果右边的数组表达式中包含null元素并且比较结果没有假值,则ALL的结果将是NULL(某些不严格的比较操作符可能得到不同的结果), 而不是真。这样的处理方式和SQL返回空值的布尔组合规则是一致的。

    示例

openGauss=# SELECT 8000+500 < ALL (array[10000,9000]) AS RESULT;
     result
    ----------
     t
    (1 row)

17.5 行表达式

语法如下:

row_constructor operator row_constructor

两边都是一个行构造器,两行值必须具有相同数目的字段,每一行都进行比较,行比较允许使用=,<>,<,<=,>=等操作符,或其中一个相似的语义符。

=<>和别的操作符使用略有不同。如果两行值的所有字段都是非空并且相等,则认为两行是相等的;如果两行值的任意字段为非空并且不相等,则认为两行是不相等的;否则比较结果是未知的(null)。

对于<,<=,>,> =的情况下,行中元素从左到右依次比较,直到遇到一对不相等的元素或者一对为空的元素。如果这对元素中存在至少一个null值,则比较结果是未知的(null),否则这对元素的比较结果为最终的结果。

示例:

openGauss=# SELECT ROW(1,2,NULL) < ROW(1,3,0) AS RESULT;
 result
----------
 t
(1 row)

👍 点赞,你的认可是我创作的动力!

⭐️ 收藏,你的青睐是我努力的方向!

✏️ 评论,你的意见是我进步的财富!

image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,192评论 6 511
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,858评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,517评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,148评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,162评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,905评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,537评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,439评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,956评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,083评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,218评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,899评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,565评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,093评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,201评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,539评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,215评论 2 358

推荐阅读更多精彩内容