SELECT 嵌套查询,使用 WITH +cte 通用表表达式

Open SQL 关键字:WITH

Open SQL 语句。引入一个或多个通用表表达式 +cte1+cte2 的定义,用于关闭主查询 SELECT … 通用表表达式的结果集由子查询子查询决定。

通用表表达式(common table expression)

通用表表达式(简称 CTE)在 Open SQL 语句 WITH 中使用子查询进行定义。WITH 语句的主查询访问通用表表达式。

语法:

WITH
  +cte1[( name1, name2, ... )] AS ( SELECT subquery_clauses [UNION ...] )[,
  +cte2[( name1, name2, ... )] AS ( SELECT subquery_clauses [UNION ...] ),
  ... ]
  SELECT mainquery_clauses
         [UNION ...]
         INTO|APPENDING target
         [additional_options].
  ...
[ENDWITH].

WITH 引入了在最终主查询中使用的通用表表达式(简称 CTE)的定义。WITH 可以作为独立语句使用(如图所示),也可以在 OPEN CURSOR 语句之后使用。

每个通用表达式都会在子查询中创建一个表格结果集,该结果集可作为数据源 data_source 用于 WITH 语句的后续查询。

WITH 语句由以下部分组成:

  • 以逗号分隔的列表,其中包含至少一个通用表表达式定义
    • 每个通用表达式都有一个唯一的名称 +cte1+cte2、…。名称 cte 最多可以有 30 个字符,可以包含字母、数字和下划线。它们必须以字母或下划线开头。此外,名称的前缀必须是 + 字符。首字母 + 字符是名称的一部分,但不能单独存在,后面也不能有数字。
    • 可以在名称后直接指定一个可选的名称列表(name1name2、…),用于指定通用表表达式结果集的列名(见下文)。
    • AS 后面有一个带括号的子查询 SELECT subquery_clauses。该子查询创建通用表表达式的表格结果集。语言元素 UNION 可用来组合多个子查询的结果集。在这种情况下,附加规则 query_clauses 适用于指定子查询。
  • 封闭式主查询 SELECT mainquery_clauses,它可以包含与独立 SELECT 语句相同的子句和添加内容(FOR ALL ENTRIES 除外),工作方式也相同:
    • 主查询的结果集根据 INTO 子句分配给 ABAP 数据对象。
    • SELECT 中所述,创建单行或多行结果集,并根据 INTO 子句中指定的目标区域,打开或不打开 SELECT 循环。
    • SELECT 循环必须以 ENDWITH 语句结束。对于 WITH ... SELECT 时,ENDWITH 与独立 SELECT 循环的 ENDSELECT 意义完全相同。
    • 在主查询中,之前定义的每个通用表表达式 +cte1+cte2 等都可用作数据源 data_source。

语言元素 UNION 可用来组合多个主查询的结果集。在这种情况下,附加的 query_clauses 规则适用于指定子句。

WITH 语句中定义的通用表表达式在定义后可以在另一个共用表表达式的子查询中使用,并在主查询中作为数据源 data_source 使用。它不能在自己的子查询中使用,也不能在前面定义的子查询中使用。通用表表达式只能在当前 WITH 语句中使用。

WITH 语句中定义的每个通用表表达式必须在 WITH 语句中至少使用一次,可以在另一个通用表表达式中使用,也可以在主查询中使用。也就是说,主查询必须访问至少一个通用表表达式。

通用表表达式的名称 +cte 在整个 WITH 语句中有效。只有在 INTO 子句中将子结构创建为通用表表达式的数据源时,子结构名称中的 + 字符才会被省略。

通用表表达式的结果集永远不会 client 列。即使在子查询中将客户专用数据源的客户列明确添加到其 SELECT 列表中,在结果集中也不会有客户列。因此,在使用普通表表达式作为数据源的 WITH 语句查询中,不能指定添加 CLIENT SPECIFIED

Notes:

  • 通用表表达式会创建一个临时表格结果集,可在执行 WITH 语句期间访问该结果集。因此,可以将通用表表达式视为临时视图,它只在数据库访问期间存在。
  • 只要 SELECT 语句中需要小计,就可以使用通用表表达式。如果使用通用表表达式,开放式 SQL 语句的可读性会更高,而且如果需要多次使用小计,通用表表达式总是很有用。如果需要,通用表表达式还可以执行 GTTs 的任务。
  • 使用通用表表达式还可以直接从子查询 SELECT FROM 子查询中进行选择,这在 Open SQL 中是不可能实现的。
  • 作为前缀的字符 + 将表表达式标记为通用表表达式,就像主机变量的字符 @ 一样。字符 + 可以防止通用表表达式与 ABAP 字典中的表具有相同的名称,从而使其模糊不清。
  • 对于用 ENDWITH 结束的 WITH 循环,与 SELECT 循环的注意事项相同。特别是,WITH 循环不应嵌套。
  • WITH 语句的查询中可以添加 CLIENT SPECIFIED(客户指定的数据源),以停用客户自动处理功能。
  • WITH 语句的主查询中,如果在 SELECT 列表中指定了 *,则表示没有未转换的数据传输到 INTO 后指定的工作区
  • WITH 语句绕过了 SAP 缓冲
  • 如果使用 WITH 语句,语法缓冲将在 7.51 版的严格模式下执行。

示例

通用表表达式 +cities 的结果集是航空公司飞往或飞离的所有城市的列表。通用表表达式在主查询中用作 WHERE 条件子查询的数据源。

DATA carrid TYPE spfli-carrid VALUE 'LH'.
cl_demo_input=>request( CHANGING field = carrid ).

WITH
  +cities AS (
    SELECT cityfrom AS city
           FROM spfli
           WHERE carrid = @carrid
    UNION DISTINCT
    SELECT cityto AS city
           FROM spfli
           WHERE carrid = @carrid )
  SELECT *
         FROM sgeocity
         WHERE city IN ( SELECT city
                                FROM +cities )
         INTO TABLE @DATA(result).

cl_demo_output=>display( result ).

… ( name1, name2, … )

定义通用表表达式 +cte 的列名。指定的名称 name1、name2… 将按给定的顺序分配给通用表表达式子查询 SELECT 列表中定义的列。这些名称的作用类似于使用 AS 在 SELECT 列表中定义的替代列名,并会覆盖这些名称。

  • 如果指定了名称列表,该列表必须包含通用表表达式中每一列的名称
  • 如果没有指定名称列表,则结果列表中的列将使用子查询 SELECT 列表中定义的名称。

开头括号必须直接位于 +cte1、+cte2 等名称之后。在开头括号之后和结尾括号之前必须至少有一个空格。逗号分隔的名称列表中可以有空白。

名称最多可以有 30 个字符,可以包含字母、数字和下划线。名称必须以字母或下划线开头。

注意:
如果在子查询的 SELECT 列表中选择了所有带 * 的列,则可以指定名称列表。如果扩展子查询的数据源,这可能会导致语法错误。

示例:

通用表表达式 +connections+sum_seats 的结果集在通用表表达式 +result 的子查询中合并为一个连接表达式。显式名称列表为结果列分配名称。这些名称在主查询中用于对结果进行排序。对于所选航空公司的每个航班连接,占用座位总数将从数据库表 SFLIGHT 中输出。

DATA from_id TYPE spfli-carrid VALUE 'AA'.
cl_demo_input=>add_field( CHANGING field = from_id ).
DATA to_id TYPE spfli-carrid VALUE 'UA'.
cl_demo_input=>request( CHANGING field = to_id ).
from_id = to_upper( from_id ).
to_id   = to_upper( to_id ).

WITH
  +connections AS (
    SELECT spfli~carrid, carrname, connid, cityfrom, cityto
           FROM spfli
           INNER JOIN scarr
             ON scarr~carrid = spfli~carrid
           WHERE spfli~carrid BETWEEN @from_id AND @to_id ),
  +sum_seats AS (
    SELECT carrid, connid, SUM( seatsocc ) AS sum_seats
           FROM sflight
           WHERE carrid BETWEEN @from_id AND @to_id
           GROUP BY carrid, connid ),
  +result( name, connection, departure, arrival, occupied ) AS (
    SELECT carrname, c~connid, cityfrom, cityto, sum_seats
           FROM +connections AS c
             INNER JOIN +sum_seats AS s
               ON c~carrid = s~carrid AND
                  c~connid = s~connid )
  SELECT *
         FROM +result
         ORDER BY name, connection
         INTO TABLE @DATA(result).

cl_demo_output=>display( result ).
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值