SELECT

    SELECT语句就像叠加在数据库表上的过滤器,利用SQL关键字从数据表中过滤出用户需要的数据。

    • 必须对每个在SELECT命令中使用的字段有SELECT权限。

    • 使用FOR UPDATE或FOR SHARE还要求UPDATE权限。

    • 查询数据
    • 其中子查询with_query为:

      1. AS ( {select | values | insert | update | delete} )
    • 其中指定查询源from_item为:

    • 其中group子句为:

      1. ( )
      2. | expression
      3. | ( expression [, ...] )
      4. | ROLLUP ( { expression | ( expression [, ...] ) } [, ...] )
      5. | CUBE ( { expression | ( expression [, ...] ) } [, ...] )
      6. | GROUPING SETS ( grouping_element [, ...] )
    • 其中指定分区partition_clause为:

      说明: 指定分区只适合普通表。

    • 其中设置排序方式nlssort_expression_clause为:

      1. NLSSORT ( column_name, ' NLS_SORT = { SCHINESE_PINYIN_M | generic_m_ci } ' )
    • 简化版查询语法,功能相当于select * from table_name。

    • WITH [ RECURSIVE ] with_query [, …]

      用于声明一个或多个可以在主查询中通过名称引用的子查询,相当于临时表。

      如果声明了RECURSIVE,那么允许SELECT子查询通过名称引用它自己。

      其中with_query的详细格式为:with_query_name [ ( column_name [, …] ) ] AS( {select | values | insert | update | delete} )

      • with_query_name指定子查询生成的结果集名称,在查询中可使用该名称访问子查询的结果集。
      • column_name指定子查询结果集中显示的列名。
      • 每个子查询可以是SELECT,VALUES,INSERT,UPDATE或DELETE语句。
    • plan_hint子句

      以/*+ */的形式在SELECT关键字后,用于对SELECT对应的语句块生成的计划进行hint调优,详细用法请参见章节。每条语句中只有第一个/*+ plan_hint */注释块会作为hint生效,里面可以写多条hint。

    • ALL

      声明返回所有符合条件的行,是默认行为,可以省略该关键字。

    • DISTINCT [ ON ( expression [, …] ) ]

      从SELECT的结果集中删除所有重复的行,使结果集中的每行都是唯一的。

      ON ( expression [, …] ) 只保留那些在给出的表达式上运算出相同结果的行集合中的第一行。

      SELECT - 图3 须知: DISTINCT ON表达式是使用与ORDER BY相同的规则进行解释的。除非使用了ORDER BY来保证需要的行首先出现,否则,”第一行” 是不可预测的。

    • SELECT列表

      指定查询表中列名,可以是部分列或者是全部(使用通配符*表示)。

      通过使用子句AS output_name可以为输出字段取个别名,这个别名通常用于输出字段的显示。支持关键字name、value和type作为列别名。

      列名可以用下面几种形式表达:

      • 手动输入列名,多个列之间用英文逗号(,)分隔。
      • 可以是FROM子句里面计算出来的字段。
    • FROM子句

      为SELECT声明一个或者多个源表。

      FROM子句涉及的元素如下所示。

      • table_name

        表名或视图名,名称前可加上模式名,如:schema_name.table_name。

      • alias

        给表或复杂的表引用起一个临时的表别名,以便被其余的查询引用。

        别名用于缩写或者在自连接中消除歧义。如果提供了别名,它就会完全隐藏表的实际名称。

      • TABLESAMPLE sampling_method ( argument [, …] ) [ REPEATABLE ( seed ) ]

        table_name之后的TABLESAMPLE子句表示应该用指定的sampling_method来检索表中行的子集。

        可选的REPEATABLE子句指定一个用于产生采样方法中随机数的种子数。种子值可以是任何非空常量值。如果查询时表没有被更改,指定相同种子和argument值的两个查询将会选择该表相同的采样。但是不同的种子值通常将会产生不同的采样。如果没有给出REPEATABLE,则会基于一个系统产生的种子为每一个查询选择一个新的随机采样。

      • TIMECAPSULE { TIMESTAMP | CSN } expression

        查询指定CSN点或者指定时间点表的内容。

        目前不支持闪回查询的表:系统表、列存表、内存表、DFS表、全局临时表、本地临时表、UNLOGGED表、分区表、视图、序列表、Hbkt表、共享表、继承表、带有PARTIAL CLUSTER KEY约束的表。

        • TIMECAPSULE TIMESTAMP

          关键字,闪回查询的标识,根据date日期,闪回查找指定时间点的结果集。date日期必须是一个过去有效的时间戳。

        • TIMECAPSULE CSN

          关键字,闪回查询的标识,根据表的CSN闪回查询指定CSN点的结果集。其中CSN可从gs_txn_snapshot记录的snpcsn号查得。

      • column_alias

      • PARTITION

        查询分区表的某个分区的数据。

      • partition_name

        分区名。

      • partition_value

        指定的分区键值。在创建分区表时,如果指定了多个分区键,可以通过PARTITION FOR子句指定的这一组分区键的值,唯一确定一个分区。

      • subquery

        FROM子句中可以出现子查询,创建一个临时表保存子查询的输出。

      • with_query_name

        WITH子句同样可以作为FROM子句的源,可以通过WITH查询的名称对其进行引用。

      • function_name

        函数名称。函数调用也可以出现在FROM子句中。

      • join_type

        有5种类型,如下所示。

        • [ INNER ] JOIN

          一个JOIN子句组合两个FROM项。可使用圆括弧以决定嵌套的顺序。如果没有圆括弧,JOIN从左向右嵌套。

          在任何情况下,JOIN都比逗号分隔的FROM项绑定得更紧。

        • LEFT [ OUTER ] JOIN

          返回笛卡尔积中所有符合连接条件的行,再加上左表中通过连接条件没有匹配到右表行的那些行。这样,左边的行将扩展为生成表的全长,方法是在那些右表对应的字段位置填上NULL。请注意,只在计算匹配的时候,才使用JOIN子句的条件,外层的条件是在计算完毕之后施加的。

        • RIGHT [ OUTER ] JOIN

          返回所有内连接的结果行,加上每个不匹配的右边行(左边用NULL扩展)。

          这只是一个符号上的方便,因为总是可以把它转换成一个LEFT OUTER JOIN,只要把左边和右边的输入互换位置即可。

        • FULL [ OUTER ] JOIN

          返回所有内连接的结果行,加上每个不匹配的左边行(右边用NULL扩展),再加上每个不匹配的右边行(左边用NULL扩展)。

        • CROSS JOIN

          CROSS JOIN等效于INNER JOIN ON(TRUE) ,即没有被条件删除的行。这种连接类型只是符号上的方便,因为它们与简单的FROM和WHERE的效果相同。

          说明: 必须为INNER和OUTER连接类型声明一个连接条件,即NATURAL ON,join_condition,USING (join_column [, …]) 之一。但是它们不能出现在CROSS JOIN中。

        其中CROSS JOIN和INNER JOIN生成一个简单的笛卡尔积,和在FROM的顶层列出两个项的结果相同。

      • ON join_condition

        连接条件,用于限定连接中的哪些行是匹配的。如:ON left_table.a = right_table.a。

      • USING(join_column[,…])

        ON left_table.a = right_table.a AND left_table.b = right_table.b … 的简写。要求对应的列必须同名。

      • NATURAL

        NATURAL是具有相同名称的两个表的所有列的USING列表的简写。

      • from item

        用于连接的查询源对象的名称。

    • WHERE子句

      WHERE子句构成一个行选择表达式,用来缩小SELECT查询的范围。condition是返回值为布尔型的任意表达式,任何不满足该条件的行都不会被检索。

      WHERE子句中可以通过指定”(+)“操作符的方法将表的连接关系转换为外连接。但是不建议用户使用这种用法,因为这并不是SQL的标准语法,在做平台迁移的时候可能面临语法兼容性的问题。同时,使用”(+)“有很多限制:

      1. “(+)“只能出现在where子句中。
      2. 如果from子句中已经有指定表连接关系,那么不能再在where子句中使用”(+)“。
      3. “(+)“只能作用在表或者视图的列上,不能作用在表达式上。
      4. 如果表A和表B有多个连接条件,那么必须在所有的连接条件中指定”(+)“,否则”(+)“将不会生效,表连接会转化成内连接,并且不给出任何提示信息。
      5. “(+)“作用的连接条件中的表不能跨查询或者子查询。如果”(+)“作用的表,不在当前查询或者子查询的from子句中,则会报错。如果”(+)“作用的对端的表不存在,则不报错,同时连接关系会转化为内连接。
      6. “(+)“作用的表达式不能直接通过”OR”连接。
      7. 如果”(+)“作用的列是和一个常量的比较关系, 那么这个表达式会成为join条件的一部分。
      8. 同一个表不能对应多个外表。
      9. “(+)“只能出现”比较表达式”,”NOT表达式”,“ANY表达式”,“ALL表达式”,“IN表达式”,“NULLIF表达式”,“IS DISTINCT FROM表达式”,“IS OF”表达式。”(+)“不能出现在其他类型表达式中,并且这些表达式中不允许出现通过“AND”和“OR”连接的表达式。
      10. “(+)“只能转化为左外连接或者右外连接,不能转化为全连接,即不能在一个表达式的两个表上同时指定”(+)“

      SELECT - 图6 须知: 对于WHERE子句的LIKE操作符,当LIKE中要查询特殊字符“%”、“_”、“\”的时候需要使用反斜杠“\”来进行转义。

    • START WITH

      START WITH子句通常与CONNECT BY子句同时出现, 是一种递归语句对数据进行图遍历。START WITH代表递归的初始条数,CONNECT BY条件中可以对列指定PRIOR关键字。代表以这列为递归进行递归。当前约束只能对表中的列指定PRIOR,不支持对表达式、类型转换指定PRIOR关键字。

    • GROUP BY子句

      将查询结果按某一列或多列的值分组,值相等的为一组。

      • CUBE ( { expression | ( expression [, …] ) } [, …] )

        CUBE是自动对group by子句中列出的字段进行分组汇总,结果集将包含维度列中各值的所有可能组合,以及与这些维度值组合相匹配的基础行中的聚合值。它会为每个分组返回一行汇总信息, 用户可以使用CUBE来产生交叉表值。比如,在CUBE子句中给出三个表达式(n = 3),运算结果为2n = 23 = 8组。 以n个表达式的值分组的行称为常规行,其余的行称为超级聚集行。

      • GROUPING SETS ( grouping_element [, …] )

        GROUPING SETS子句是GROUP BY子句的进一步扩展,它可以使用户指定多个GROUP BY选项。 这样做可以通过裁剪用户不需要的数据组来提高效率。 当用户指定了所需的数据组时,数据库不需要执行完整CUBE或ROLLUP生成的聚合集合。

    • HAVING子句

      与GROUP BY子句配合用来选择特殊的组。HAVING子句将组的一些属性与一个常数值比较,只有满足HAVING子句中的逻辑表达式的组才会被提取出来。

    • WINDOW子句

      一般形式为WINDOW window_name AS ( window_definition ) [, …],window_name是可以被随后的窗口定义所引用的名称,window_definition可以是以下的形式:

      [ existing_window_name ]

      [ PARTITION BY expression [, …] ]

      [ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, …] ]

      [ frame_clause ]

      [ RANGE | ROWS ] frame_start

      [ RANGE | ROWS ] BETWEEN frame_start AND frame_end

      frame_start和frame_end可以是:

      UNBOUNDED PRECEDING

      value PRECEDING

      CURRENT ROW

      value FOLLOWING

      UNBOUNDED FOLLOWING

      须知: 对列存表的查询目前只支持row_number窗口函数,不支持frame_clause。

    • UNION子句

      UNION计算多个SELECT语句返回行集合的并集。

      UNION子句有如下约束条件:

      • 除非声明了ALL子句,否则缺省的UNION结果不包含重复的行。
      • 同一个SELECT语句中的多个UNION操作符是从左向右计算的,除非用圆括弧进行了标识。
      • FOR UPDATE不能在UNION的结果或输入中声明。

      一般表达式:

      select_statement UNION [ALL] select_statement

      • select_statement可以是任何没有ORDER BY、LIMIT、FOR UPDATE子句的SELECT语句。
      • 如果用圆括弧包围,ORDER BY和LIMIT可以附着在子表达式里。
    • INTERSECT子句

      INTERSECT计算多个SELECT语句返回行集合的交集,不含重复的记录。

      INTERSECT子句有如下约束条件:

      • 同一个SELECT语句中的多个INTERSECT操作符是从左向右计算的,除非用圆括弧进行了标识。
      • 当对多个SELECT语句的执行结果进行UNION和INTERSECT操作的时候,会优先处理INTERSECT。

      一般形式:

      select_statement INTERSECT select_statement

      select_statement可以是任何没有FOR UPDATE子句的SELECT语句。

    • EXCEPT子句

      EXCEPT子句有如下的通用形式:

      select_statement EXCEPT [ ALL ] select_statement

      select_statement是任何没有FOR UPDATE子句的SELECT表达式。

      EXCEPT操作符计算存在于左边SELECT语句的输出而不存在于右边SELECT语句输出的行。

      EXCEPT的结果不包含任何重复的行,除非声明了ALL选项。使用ALL时,一个在左边表中有m个重复而在右边表中有n个重复的行将在结果中出现max(m-n,0) 次。

      除非用圆括弧指明顺序,否则同一个SELECT语句中的多个EXCEPT操作符是从左向右计算的。EXCEPT和UNION的绑定级别相同。

      目前,不能给EXCEPT的结果或者任何EXCEPT的输入声明FOR UPDATE子句。

    • MINUS子句

      与EXCEPT子句具有相同的功能和用法。

    • ORDER BY子句

      对SELECT语句检索得到的数据进行升序或降序排序。对于ORDER BY表达式中包含多列的情况:

      • 首先根据最左边的列进行排序,如果这一列的值相同,则根据下一个表达式进行比较,依此类推。
      • 如果对于所有声明的表达式都相同,则按随机顺序返回。
      • 在与GROUP BY子句一起使用的情况下,ORDER BY中排序的列必须包括在SELECT语句所检索的结果集的列中。

      SELECT - 图9 须知: 如果要支持中文拼音排序,需要在初始化数据库时指定编码格式为UTF-8或GBK。 命令如下: initdb –E UTF8 –D ../data –locale=zh_CN.UTF-8或initdb –E GBK –D ../data –locale=zh_CN.GBK。

    • LIMIT子句

      LIMIT子句由两个独立的子句组成:

      LIMIT { count | ALL }

      OFFSET start count声明返回的最大行数,而start声明开始返回行之前忽略的行数。如果两个都指定了,会在开始计算count个返回行之前先跳过start行。

    • OFFSET子句

      SQL:2008开始提出一种不同的语法:

      OFFSET start { ROW | ROWS }

      start声明开始返回行之前忽略的行数。

    • FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY

      如果不指定count,默认值为1,FETCH子句限定返回查询结果从第一行开始的总行数。

    • FOR UPDATE子句

      FOR UPDATE子句将对SELECT检索出来的行进行加锁。这样避免它们在当前事务结束前被其他事务修改或者删除,即其他企图UPDATE、 DELETE、 SELECT FOR UPDATE这些行的事务将被阻塞,直到当前事务结束。

      为了避免操作等待其他事务提交,可使用NOWAIT选项,如果被选择的行不能立即被锁住,执行SELECT FOR UPDATE NOWAIT将会立即汇报一个错误,而不是等待。

      FOR SHARE的行为类似,只是它在每个检索出来的行上要求一个共享锁,而不是一个排他锁。一个共享锁阻塞其它事务执行UPDATE、DELETE、SELECT,不阻塞SELECT FOR SHARE。

      如果在FOR UPDATE或FOR SHARE中明确指定了表名称,则只有这些指定的表被锁定,其他在SELECT中使用的表将不会被锁定。否则,将锁定该命令中所有使用的表。

      如果FOR UPDATE或FOR SHARE应用于一个视图或者子查询,它同样将锁定所有该视图或子查询中使用到的表。

      多个FOR UPDATE和FOR SHARE子句可以用于为不同的表指定不同的锁定模式。

      如果一个表中同时出现(或隐含同时出现)在FOR UPDATE和FOR SHARE子句中,则按照FOR UPDATE处理。类似的,如果影响一个表的任意子句中出现了NOWAIT,该表将按照NOWAIT处理。

    • NLS_SORT

      指定某字段按照特殊方式排序。目前仅支持中文拼音格式排序和不区分大小写排序。

      取值范围:

      • SCHINESE_PINYIN_M,按照中文拼音排序。如果要支持此排序方式,在创建数据库时需要指定编码格式为“UTF8”或“GBK”,否则排序无效。
      • generic_m_ci,不区分大小写排序。
    • PARTITION子句

      查询某个分区表中相应分区的数据。

    1. --先通过子查询得到一张临时表temp_t,然后查询表temp_t中的所有数据。
    2. openGauss=# WITH temp_t(name,isdba) AS (SELECT usename,usesuper FROM pg_user) SELECT * FROM temp_t;
    3. --查询tpcds.reason表的所有r_reason_sk记录,且去除重复。
    4. openGauss=# SELECT DISTINCT(r_reason_sk) FROM tpcds.reason;
    5. --LIMIT子句示例:获取表中一条记录。
    6. openGauss=# SELECT * FROM tpcds.reason LIMIT 1;
    7. --查询所有记录,且按字母升序排列。
    8. openGauss=# SELECT r_reason_desc FROM tpcds.reason ORDER BY r_reason_desc;
    9. --通过表别名,从pg_userpg_user_status这两张表中获取数据。
    10. openGauss=# SELECT a.usename,b.locktime FROM pg_user a,pg_user_status b WHERE a.usesysid=b.roloid;
    11. --FULL JOIN子句示例:将pg_userpg_user_status这两张表的数据进行全连接显示,即数据的合集。
    12. openGauss=# SELECT a.usename,b.locktime,a.usesuper FROM pg_user a FULL JOIN pg_user_status b on a.usesysid=b.roloid;
    13. --GROUP BY子句示例:根据查询条件过滤,并对结果进行分组。
    14. openGauss=# SELECT r_reason_id, AVG(r_reason_sk) FROM tpcds.reason GROUP BY r_reason_id HAVING AVG(r_reason_sk) > 25;
    15. --GROUP BY CUBE子句示例:根据查询条件过滤,并对结果进行分组汇总。
    16. openGauss=# SELECT r_reason_id,AVG(r_reason_sk) FROM tpcds.reason GROUP BY CUBE(r_reason_id,r_reason_sk);
    17. --GROUP BY GROUPING SETS子句示例:根据查询条件过滤,并对结果进行分组汇总。
    18. openGauss=# SELECT r_reason_id,AVG(r_reason_sk) FROM tpcds.reason GROUP BY GROUPING SETS((r_reason_id,r_reason_sk),r_reason_sk);
    19. --UNION子句示例:将表tpcds.reasonr_reason_desc字段中的内容以W开头和以N开头的进行合并。
    20. openGauss=# SELECT r_reason_sk, tpcds.reason.r_reason_desc
    21. FROM tpcds.reason
    22. WHERE tpcds.reason.r_reason_desc LIKE 'W%'
    23. UNION
    24. SELECT r_reason_sk, tpcds.reason.r_reason_desc
    25. FROM tpcds.reason
    26. WHERE tpcds.reason.r_reason_desc LIKE 'N%';
    27. --NLS_SORT子句示例:中文拼音排序。
    28. openGauss=# SELECT * FROM tpcds.reason ORDER BY NLSSORT( r_reason_desc, 'NLS_SORT = SCHINESE_PINYIN_M');
    29. --不区分大小写排序:
    30. openGauss=# SELECT * FROM tpcds.reason ORDER BY NLSSORT( r_reason_desc, 'NLS_SORT = generic_m_ci');
    31. --创建分区表tpcds.reason_p
    32. openGauss=# CREATE TABLE tpcds.reason_p
    33. (
    34. r_reason_sk integer,
    35. r_reason_id character(16),
    36. r_reason_desc character(100)
    37. )
    38. PARTITION BY RANGE (r_reason_sk)
    39. (
    40. partition P_05_BEFORE values less than (05),
    41. partition P_15 values less than (15),
    42. partition P_25 values less than (25),
    43. partition P_35 values less than (35),
    44. partition P_45_AFTER values less than (MAXVALUE)
    45. ;
    46. --插入数据。
    47. openGauss=# INSERT INTO tpcds.reason_p values(3,'AAAAAAAABAAAAAAA','reason 1'),(10,'AAAAAAAABAAAAAAA','reason 2'),(4,'AAAAAAAABAAAAAAA','reason 3'),(10,'AAAAAAAABAAAAAAA','reason 4'),(10,'AAAAAAAABAAAAAAA','reason 5'),(20,'AAAAAAAACAAAAAAA','reason 6'),(30,'AAAAAAAACAAAAAAA','reason 7');
    48. --PARTITION子句示例:从tpcds.reason_p的表分区P_05_BEFORE中获取数据。
    49. openGauss=# SELECT * FROM tpcds.reason_p PARTITION (P_05_BEFORE);
    50. r_reason_sk | r_reason_id | r_reason_desc
    51. -------------+------------------+------------------------------------
    52. 4 | AAAAAAAABAAAAAAA | reason 3
    53. 3 | AAAAAAAABAAAAAAA | reason 1
    54. (2 rows)
    55. --GROUP BY子句示例:按r_reason_id分组统计tpcds.reason_p表中的记录数。
    56. openGauss=# SELECT COUNT(*),r_reason_id FROM tpcds.reason_p GROUP BY r_reason_id;
    57. count | r_reason_id
    58. -------+------------------
    59. 2 | AAAAAAAACAAAAAAA
    60. 5 | AAAAAAAABAAAAAAA
    61. (2 rows)
    62. --GROUP BY CUBE子句示例:根据查询条件过滤,并对查询结果分组汇总。
    63. openGauss=# SELECT * FROM tpcds.reason GROUP BY CUBE (r_reason_id,r_reason_sk,r_reason_desc);
    64. --GROUP BY GROUPING SETS子句示例:根据查询条件过滤,并对查询结果分组汇总。
    65. openGauss=# SELECT * FROM tpcds.reason GROUP BY GROUPING SETS ((r_reason_id,r_reason_sk),r_reason_desc);
    66. --HAVING子句示例:按r_reason_id分组统计tpcds.reason_p表中的记录,并只显示r_reason_id个数大于2的信息。
    67. openGauss=# SELECT COUNT(*) c,r_reason_id FROM tpcds.reason_p GROUP BY r_reason_id HAVING c>2;
    68. c | r_reason_id
    69. ---+------------------
    70. (1 row)
    71. --IN子句示例:按r_reason_id分组统计tpcds.reason_p表中的r_reason_id个数,并只显示r_reason_id值为 AAAAAAAABAAAAAAAAAAAAAAADAAAAAAA的个数。
    72. openGauss=# SELECT COUNT(*),r_reason_id FROM tpcds.reason_p GROUP BY r_reason_id HAVING r_reason_id IN('AAAAAAAABAAAAAAA','AAAAAAAADAAAAAAA');
    73. count | r_reason_id
    74. -------+------------------
    75. 5 | AAAAAAAABAAAAAAA
    76. (1 row)
    77. --INTERSECT子句示例:查询r_reason_id等于AAAAAAAABAAAAAAA,并且r_reason_sk小于5的信息。
    78. openGauss=# SELECT * FROM tpcds.reason_p WHERE r_reason_id='AAAAAAAABAAAAAAA' INTERSECT SELECT * FROM tpcds.reason_p WHERE r_reason_sk<5;
    79. r_reason_sk | r_reason_id | r_reason_desc
    80. -------------+------------------+------------------------------------
    81. 4 | AAAAAAAABAAAAAAA | reason 3
    82. 3 | AAAAAAAABAAAAAAA | reason 1
    83. (2 rows)
    84. --EXCEPT子句示例:查询r_reason_id等于AAAAAAAABAAAAAAA,并且去除r_reason_sk小于4的信息。
    85. openGauss=# SELECT * FROM tpcds.reason_p WHERE r_reason_id='AAAAAAAABAAAAAAA' EXCEPT SELECT * FROM tpcds.reason_p WHERE r_reason_sk<4;
    86. r_reason_sk | r_reason_id | r_reason_desc
    87. -------------+------------------+------------------------------------
    88. 10 | AAAAAAAABAAAAAAA | reason 2
    89. 10 | AAAAAAAABAAAAAAA | reason 5
    90. 10 | AAAAAAAABAAAAAAA | reason 4
    91. 4 | AAAAAAAABAAAAAAA | reason 3
    92. (4 rows)
    93. --通过在where子句中指定"(+)"来实现左连接。
    94. openGauss=# select t1.sr_item_sk ,t2.c_customer_id from store_returns t1, customer t2 where t1.sr_customer_sk = t2.c_customer_sk(+)
    95. order by 1 desc limit 1;
    96. sr_item_sk | c_customer_id
    97. ------------+---------------
    98. 18000 |
    99. --通过在where子句中指定"(+)"来实现右连接。
    100. openGauss=# select t1.sr_item_sk ,t2.c_customer_id from store_returns t1, customer t2 where t1.sr_customer_sk(+) = t2.c_customer_sk
    101. order by 1 desc limit 1;
    102. sr_item_sk | c_customer_id
    103. ------------+------------------
    104. | AAAAAAAAJNGEBAAA
    105. (1 row)
    106. --通过在where子句中指定"(+)"来实现左连接,并且增加连接条件。
    107. openGauss=# select t1.sr_item_sk ,t2.c_customer_id from store_returns t1, customer t2 where t1.sr_customer_sk = t2.c_customer_sk(+) and t2.c_customer_sk(+) < 1 order by 1 limit 1;
    108. sr_item_sk | c_customer_id
    109. ------------+---------------
    110. 1 |
    111. (1 row)
    112. --不支持在where子句中指定"(+)"的同时使用内层嵌套AND/OR的表达式。
    113. openGauss=# select t1.sr_item_sk ,t2.c_customer_id from store_returns t1, customer t2 where not(t1.sr_customer_sk = t2.c_customer_sk(+) and t2.c_customer_sk(+) < 1);
    114. ERROR: Operator "(+)" can not be used in nesting expression.
    115. LINE 1: ...tomer_id from store_returns t1, customer t2 where not(t1.sr_...
    116. ^
    117. --where子句在不支持表达式宏指定"(+)"会报错。
    118. openGauss=# select t1.sr_item_sk ,t2.c_customer_id from store_returns t1, customer t2 where (t1.sr_customer_sk = t2.c_customer_sk(+))::bool;
    119. ERROR: Operator "(+)" can only be used in common expression.
    120. --where子句在表达式的两边都指定"(+)"会报错。
    121. openGauss=# select t1.sr_item_sk ,t2.c_customer_id from store_returns t1, customer t2 where t1.sr_customer_sk(+) = t2.c_customer_sk(+);
    122. ERROR: Operator "(+)" can't be specified on more than one relation in one join condition
    123. HINT: "t1", "t2"...are specified Operator "(+)" in one condition.
    124. --删除表。
    125. openGauss=# DROP TABLE tpcds.reason_p;
    126. --闪回查询示例
    127. --创建表tpcds.time_table
    128. openGauss=# create table tpcds.time_table(idx integer, snaptime timestamp, snapcsn bigint, timeDesc character(100));
    129. --向表tpcds.time_table中插入记录
    130. openGauss=# INSERT INTO tpcds.time_table select 1, now(),int8in(xidout(next_csn)), 'time1' from gs_get_next_xid_csn();
    131. openGauss=# INSERT INTO tpcds.time_table select 2, now(),int8in(xidout(next_csn)), 'time2' from gs_get_next_xid_csn();
    132. openGauss=# INSERT INTO tpcds.time_table select 3, now(),int8in(xidout(next_csn)), 'time3' from gs_get_next_xid_csn();
    133. openGauss=# INSERT INTO tpcds.time_table select 4, now(),int8in(xidout(next_csn)), 'time4' from gs_get_next_xid_csn();
    134. openGauss=# select * from tpcds.time_table;
    135. idx | snaptime | snapcsn | timedesc
    136. -----+----------------------------+---------+------------------------------------------------------------------------------------------------------
    137. 1 | 2021-04-25 17:50:05.360326 | 107322 | time1
    138. 2 | 2021-04-25 17:50:10.886848 | 107324 | time2
    139. 3 | 2021-04-25 17:50:16.12921 | 107327 | time3
    140. 4 | 2021-04-25 17:50:22.311176 | 107330 | time4
    141. (4 rows)
    142. openGauss=# delete tpcds.time_table;
    143. DELETE 4
    144. openGauss=# SELECT * FROM tpcds.time_table TIMECAPSULE TIMESTAMP to_timestamp('2021-04-25 17:50:22.311176','YYYY-MM-DD HH24:MI:SS.FF');
    145. idx | snaptime | snapcsn | timedesc
    146. -----+----------------------------+---------+------------------------------------------------------------------------------------------------------
    147. 1 | 2021-04-25 17:50:05.360326 | 107322 | time1
    148. 2 | 2021-04-25 17:50:10.886848 | 107324 | time2
    149. 3 | 2021-04-25 17:50:16.12921 | 107327 | time3
    150. (3 rows)
    151. openGauss=# SELECT * FROM tpcds.time_table TIMECAPSULE CSN 107330;
    152. idx | snaptime | snapcsn | timedesc
    153. -----+----------------------------+---------+------------------------------------------------------------------------------------------------------
    154. 1 | 2021-04-25 17:50:05.360326 | 107322 | time1
    155. 2 | 2021-04-25 17:50:10.886848 | 107324 | time2