「SAP ABAP」OPEN SQLGROUP BY | HAVING | ORDER BY

Posted ThundersArk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「SAP ABAP」OPEN SQLGROUP BY | HAVING | ORDER BY相关的知识,希望对你有一定的参考价值。

💂作者简介: THUNDER王,一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学本科在读,同时任汉硕云(广东)科技有限公司ABAP开发顾问。在学习工作中,我通常使用偏后端的开发语言ABAP,SQL进行任务的完成,对SAP企业管理系统,SAP ABAP开发和数据库具有较深入的研究。


💅文章概要: 各位小伙伴们大家好呀!今天继续SAP ABAP系列文章的讲解,本节带来的内容是OPEN SQL中GROUP BY语句和HAVING语句以及ORDER BY语句的介绍,希望大家喜欢!


🤟每日一言: 永远年轻,永远热泪盈眶!

目录


前言

  GROUP BY语句,HAVING语句以及ORDER BY语句在SAP ABAP中起到了关键的作用。通过上述语句可以实现对数据的分组,条件限定,排序等等,可以更加有效地帮助我们从数据库表中取到想要的数据,跟着本文的脚步,一起学习吧!


数据库表准备

  本文所有案例都是基于数据库表SFLIGHT,本案例中的SFLIGHT数据库表数据如下,供各位小伙伴们对照来观察代码运行结果:


GROUP BY语句介绍



  以下是从数据库表中读取数据并且对数据进行分组聚合的一般语法样式:

SELECT <f1>  <f2> ... <fn> <aggregate>...AS <alias>
FROM <table_name>
GROUP BY <f1> <f2>...<fn> <aggregate>
INTO [CORRESPONDING FIELDS OF TABLE] <itab>
WHERE <condition>

参数介绍:

  • <fn>: 数据库表中字段。
  • <aggregate>: 聚合函数。
  • <alias>: 聚合函数别名
  • <table_name>: 数据库表的名称。
  • <itab>:存放数据的内表。
  • <condition>:WHERE子句限定条件

 案例演示

  下面给出一段以SFLIGHT数据库表为基准的示例代码,详细讲解了ABAP OPEN SQL中如何使用GROUP BY语句对数据进行分类,仅供参考:

PS:使用GROUP BY语句的先决条件是查询数据时使用了聚合函数,聚合函数将在下面讲解;并且最好使用OPEN SQL的新语法

SELECT carrid,connid,SUM( price ) AS total_price
FROM sflight
INTO TABLE @DATA(gt_sflight)
GROUP BY carrid,connid.

LOOP AT gt_sflight INTO DATA(gs_sflight).
  WRITE: / gs_sflight-carrid,gs_sflight-connid,gs_sflight-total_price.
ENDLOOP.

  这段代码主要目的是从表 SFLIGHT中获取每个航空公司和航班连接的总价格,并将其存储在名为gt_sflight的内部表中,然后使用循环读取内部表并输出每个航空公司和航班连接的总价格。

  下面是对代码的逐段分析:

  (一)第一段代码分析

SELECT carrid, connid, SUM(price) AS total_price
FROM sflight
INTO TABLE @DATA(gt_sflight)
GROUP BY carrid, connid.

  这段代码是从表 SFLIGHT 中选择carridconnidprice列,并使用 SUM 聚合函数将每个航空公司和航班连接的价格相加。然后使用 INTO TABLE 将结果存储在名为gt_sflight的内部表中,并按照 carrid 和 connid 列进行分组

  (二)第二段代码分析

LOOP AT gt_sflight INTO DATA(gs_sflight).

  这行代码是使用LOOP AT 语句遍历 gt_sflight 内部表中的每个记录,并将每个记录存储在名为 gs_sflight 的工作区域变量中。

  (三)第三段代码分析

WRITE: / gs_sflight-carrid, gs_sflight-connid, gs_sflight-total_price.

  这行代码使用 WRITE 语句将每个记录的 carrid、connid 和 total_price 列的值输出到控制台屏幕。斜杠符号表示将每个记录的值输出到新的行


聚合函数简介


  在ABAP Open SQL中,可以使用聚合函数对数据库中的数据进行汇总和统计。

聚合函数名称功能简介
AVG取平均值
COUNT取个数
MAX取最大值
MIN取最小值
STDDEV取标准偏差
SUM取合计
  • 在使用GROUP BY语句之前,必须要先使用聚合函数对数据进行汇总和统计!
  • 聚合函数括号中的字段需要与两边的括号距离至少一个单位:
    错误写法:SUM(PRICE)
    正确写法: SUM( PRICE )

HAVING语句介绍


  HAVING语句用于在GROUP BY子句之后对聚合结果进行过滤。HAVING语句与WHERE语句非常相似,但它们用于不同的语句部分。

注意事项
HAVING语句必须跟在GROUP BY子句之后。
HAVING语句使用与WHERE语句相同的语法。
HAVING语句中的条件必须是聚合函数。


  以下是对数据分组并且对聚合结果进行过滤的一般语法样式:

SELECT <f1>  <f2> ... <fn> <aggregate>...AS <alias>
FROM <table_name>
GROUP BY <f1> <f2>...<fn> <aggregate>
HAVING <agg_condition>
INTO [CORRESPONDING FIELDS OF TABLE] <itab>
WHERE <condition>

参数介绍:

  • <fn>: 数据库表中字段。
  • <aggregate>: 聚合函数。
  • <alias>: 聚合函数别名
  • <table_name>: 数据库表的名称。
  • <agg_condition>: 聚合结果过滤条件。
  • <itab>:存放数据的内表。
  • <condition>:WHERE子句限定条件

 案例演示

  下面给出一段以SFLIGHT数据库表为基准的示例代码,详细讲解了ABAP OPEN SQL中如何使用HAVING语句对数据聚合结果进行过滤,仅供参考:

SELECT carrid,connid,SUM( price ) AS total_price
FROM sflight
INTO TABLE @DATA(gt_sflight)
      GROUP BY carrid,connid
      HAVING SUM( price ) > 1000.

LOOP AT gt_sflight INTO DATA(gs_sflight).
  WRITE: / gs_sflight-carrid,gs_sflight-connid,gs_sflight-total_price.
ENDLOOP.

  该段代码在GROUP BY语句案例演示中的的基础上增加了一个HAVING语句,过滤了total_price < 1000的数据。


ORDER BY语句介绍

  ABAP中的ORDER BY语句用于对数据库表中的数据进行排序。排序可以按照单个字段多个字段进行,可以按照升序降序排列。

  以下是对数据分组并且对聚合结果进行过滤以及最终对字段进行排序的一般语法样式:

SELECT <f1>  <f2> ... <fn> <aggregate>...AS <alias>
FROM <table_name>
GROUP BY <f1> <f2>...<fn> <aggregate>
HAVING <agg_condition>
ORDER BY <f1> <f2>...<fn> <aggregate> [ASC|DESC]
INTO [CORRESPONDING FIELDS OF TABLE] <itab>
WHERE <condition>

参数介绍:

  • <fn>: 数据库表中字段。
  • <aggregate>: 聚合函数。
  • <alias>: 聚合函数别名
  • <table_name>: 数据库表的名称。
  • <agg_condition>: 聚合结果过滤条件。
  • [ ASCENDING|DESCENDING]: 可选项:ASCENDING(默认),升序;DESCENDING,降序。
  • <itab>:存放数据的内表。
  • <condition>:WHERE子句限定条件

 单个字段排序

  下面给出一段以SFLIGHT数据库表为基准的示例代码,详细讲解了ABAP OPEN SQL中如何使用单个字段·进行排序,仅供参考:

SELECT carrid,connid,SUM( price ) AS total_price
FROM sflight
INTO TABLE @DATA(gt_sflight)
      GROUP BY carrid,connid
      HAVING SUM( price ) > 1000
      ORDER BY total_price.

LOOP AT gt_sflight INTO DATA(gs_sflight).
  WRITE: / gs_sflight-carrid,gs_sflight-connid,gs_sflight-total_price.
ENDLOOP.

  该段代码在HAVINF语句案例演示中的的基础上增加了一个ORDER BY语句,对total_price进行了升序排序。

 多个字段排序

  下面给出一段以SFLIGHT数据库表为基准的示例代码,详细讲解了ABAP OPEN SQL中如何使用多个字段·进行排序,仅供参考:

PS:如果ORDER BY语句中包含多个字段,那么排序优先级是从左往右依次递减的。也就是说,先按照第一个字段排序,如果第一个字段有相同的值,则按照第二个字段排序,以此类推。

SELECT carrid,connid,SUM( price ) AS total_price
FROM sflight
INTO TABLE @DATA(gt_sflight)
      GROUP BY carrid,connid
      HAVING SUM( price ) > 1000
      ORDER BY carrid  ASCENDING,total_price DESCENDING.

LOOP AT gt_sflight INTO DATA(gs_sflight).
  WRITE: / gs_sflight-carrid,gs_sflight-connid,gs_sflight-total_price.
ENDLOOP.

  该段代码在HAVINF语句案例演示中的的基础上增加了一个ORDER BY语句,先对carrid进行了升序排序,再对total_price进行了降序排序。

 使用ORDER BY删除数据

  除了用在SELECT语句中,ORDER BY语句还可以用在DELETE、UPDATE、INSERT等语句中。例如,可以使用ORDER BY语句删除最后一行记录

DELETE FROM sflight
ORDER BY price ASCENDING
UP TO 1 ROWS.

这段代码可以删除掉SFLIGHT数据库表中PRICE列最小的该条数据


写在最后的话

  本文花费大量时间介绍了OPEN SQL中GROUP BY语句,HAVING语句以及ORDER BY语句的详细用法,希望能帮助到各位小伙伴,码文不易,还望各位大佬们多多支持哦,你们的支持是我最大的动力!

原 创 不 易 , 还 希 望 各 位 大 佬 支 持 一 下 \\textcolorblue原创不易,还希望各位大佬支持一下

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

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

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

「SAP ABAP」OPEN SQLSELECT语句

💂作者简介: THUNDER王,一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学会计学专业大二本科在读,同时任汉硕云(广东)科技有限公司ABAP开发顾问。在学习工作中,我通常使用偏后端的开发语言ABAP,SQL进行任务的完成,对SAP企业管理系统,SAP ABAP开发和数据库具有较深入的研究。


💅文章概要: 各位小伙伴们大家好呀!今天继续SAP ABAP系列文章的讲解,本节带来的内容是OPEN SQL中SELECT语句的介绍,希望大家喜欢!


🤟每日一言: 永远年轻,永远热泪盈眶!

目录


前言

  各位小伙伴们大家好呀!今天继续SAP ABAP系列文章的讲解,本节带来的内容是OPEN SQL中SELECT语句的介绍,希望大家喜欢!


数据库表准备

  本文所有案例都是基于数据库表SFLIGHT,本案例中的SFLIGHT数据库表数据如下,供各位小伙伴们对照来观察代码运行结果:


SELECT语句介绍

  在ABAP中,SELECT语句用于从数据库表中检索数据,它与传统的SQL语句有相似之处,也有独特于ABAP的特性,下面是OPEN SQL中标准的代码语法样例:

SELECT <fields>
  FROM <table>
  [WHERE <condition>]
  [ORDER BY <fields> [ASC|DESC]]
  [GROUP BY <fields> [HAVING <condition>]]
  [INTO <internal table>]
  [FOR ALL ENTRIES IN <internal table>]
  [UP TO <n> ROWS]
  [HINT <hint>].

参数介绍:

  • <fields>:需要检索的字段列表。
  • <table>:需要从中检索数据的数据库表。
  • <condition>:可选项,用于过滤检索结果的条件。
  • <internal table>:可选项,表示检索结果将被存储在内部表中。
  • FOR ALL ENTRIES IN <internal table>:可选项,表示使用内部表中的值作为条件来检索数据。
  • <n>:可选项,表示返回的最大行数。
  • <hint>:可选项,用于优化数据库查询。

SELECT语句变式

  在ABAP中,SELECT语句不仅可以检索多行数据,还可以检索单行数据。为了满足这两种不同的检索需求,ABAP提供了两种SELECT语句的变体:SELECT SINGLESELECT SEVERAL LINE

  SELECT SINGLE

  SELECT SINGLE语句用于从数据库中检索单个行,并将其存储在内部表中。如果检索到多行数据,则只返回第一行数据

  以下是SELECT SINGLE语句的语法:

SELECT SINGLE <fields>
  FROM <table>
  [WHERE <condition>]
  [ORDER BY <fields> [ASC|DESC]]
  [INTO <internal table>]
  [FOR UPDATE].

PS:所有参数同SELECT语句介绍一致

   案例演示

  在这个案例中,首先声明一个sflight表的结构体类型ls_flight,然后使用SELECT SINGLE语句检索连接ID为0820的航班的航空公司、连接ID、日期和价格,并将数据存储在结构体ls_flight中。最后,使用WRITE语句将检索到的航班数据输出到屏幕上。

DATA: ls_flight TYPE sflight.

* Select a flight with connection ID = 0820 and store the data in a structure
SELECT SINGLE carrid, connid, fldate, price
FROM sflight
WHERE connid = '0820'
INTO CORRESPONDING FIELDS OF @ls_flight.

* Display the flight data
WRITE: / 'Flight', ls_flight-connid, 'on', ls_flight-fldate,
'with airline', ls_flight-carrid, 'costs', ls_flight-price, 'USD'.

PS:SELECT数据插入到结构体变量中需要使用新语法,需要在结构体变量前加@,并且字段间用逗号隔开。

  SELECT SEVERAL LINE

   SELECT SEVERAL LINE语句用于从数据库中检索多个行,并将其存储在内部表中。如果没有检索到数据,则返回空内部表

  以下是SELECT SEVERAL LINE语句的语法:

SELECT <fields>
  FROM <table>
  [WHERE <condition>]
  [ORDER BY <fields> [ASC|DESC]]
  [GROUP BY <fields> [HAVING <condition>]]
  [INTO <internal table>]
  [FOR ALL ENTRIES IN <internal table>]
  [UP TO <n> ROWS]
  [HINT <hint>].

PS:所有参数同SELECT语句介绍一致

   案例演示


  下面是一个案例的详细讲解:

PS:该段代码为OPEN SQL老语法格式。

DATA: lt_flight TYPE STANDARD TABLE OF sflight,
      ls_flight TYPE sflight.

* Select all flights with airline code 'LH' and store the data in an internal table
SELECT carrid connid fldate price
INTO CORRESPONDING FIELDS OF TABLE lt_flight
FROM sflight
WHERE carrid = 'LH'.

* Display the flight dataZ
WRITE: / 'Flights operated by airline LH:'.
LOOP AT lt_flight INTO ls_flight.
  WRITE: / ls_flight-connid, 'on', ls_flight-fldate, 'costs', ls_flight-price, 'USD'.
ENDLOOP.

  在这个案例中,首先声明一个内部表lt_flight,其类型为自定义类型ty_flight,该类型包含航空公司、连接ID、日期和价格字段。

  然后,使用SELECT SEVERAL LINE语句检索航空公司代码为LH的所有航班的航空公司、连接ID、日期和价格,并将数据存储在内部表lt_flight中。

  最后,使用LOOP AT语句遍历内部表中的每个航班数据,并使用WRITE语句将其输出到屏幕上。

PS:下面这段代码为上方那段代码的新语法格式。

* Select all flights with airline code 'LH' and store the data in an internal table
SELECT carrid,connid,fldate,price
INTO  TABLE @DATA(lt_flight)
FROM sflight
WHERE carrid = 'LH'.

* Display the flight dataZ
WRITE: / 'Flights operated by airline LH:'.
LOOP AT lt_flight INTO DATA(ls_flight).
  WRITE: / ls_flight-connid, 'on', ls_flight-fldate, 'costs', ls_flight-price, 'USD'.
ENDLOOP.


SELECT并输出打印

  下面介绍ABAP中两种SELECT并且输出打印的方式,其中第一种是先将数据SELECT到结构体变量中,然后输出打印;第二种是先将数据SELECT到内部表中,然后使用LOOP语句遍历内表最终输出打印到屏幕上

  SELECT……ENDSELECT


  下面给出一个详细的案例进行详解:

PS:该段代码为OPEN SQL老语法格式。

DATA:gs_sflight TYPE sflight.

SELECT * INTO gs_sflight FROM sflight WHERE carrid = 'AC'.
  WRITE:/ gs_sflight-carrid,gs_sflight-connid,gs_sflight-price.
ENDSELECT.

PS:下面这段代码为上方那段代码的新语法格式。

SELECT * INTO @DATA(gs_sflight) FROM sflight WHERE carrid = 'AC'.

  WRITE:/ gs_sflight-carrid,gs_sflight-connid,gs_sflight-price.
ENDSELECT.

  SELECT(LOOP……ENDLOOP)


  下面给出一个详细的案例进行详解:

PS:该段代码为OPEN SQL老语法格式。

DATA: gt_sflight TYPE TABLE OF sflight.
DATA: gs_sflight TYPE sflight.

SELECT * INTO CORRESPONDING FIELDS OF TABLE gt_sflight FROM sflight WHERE carrid = 'AC'.

LOOP AT gt_sflight INTO gs_sflight.
  WRITE:/ gs_sflight-carrid,gs_sflight-connid,gs_sflight-price.
ENDLOOP.

PS:下面这段代码为上方那段代码的新语法格式。

SELECT * INTO TABLE @DATA(gt_sflight) FROM sflight WHERE carrid = 'AC'.
LOOP AT gt_sflight INTO DATA(gs_sflight).
  WRITE:/ gs_sflight-carrid,gs_sflight-connid,gs_sflight-price.
ENDLOOP.


SELECT……AS

  在ABAP中,使用SELECT AS可以为查询结果的列定义别名。这对于使用SELECT语句构建动态SQL语句生成报表非常有用。

SELECT <columns> AS <alias>...

参数介绍

  • <columns>:数据库表中字段。
  • <alias>:字段别名。


  下面给出一个详细的案例进行详解:

SELECT carrid AS airline_code,
connid AS connection_id,
price  AS airplane_price
INTO TABLE @DATA(gt_sflight)
FROM sflight
WHERE carrid = 'LH'.

LOOP AT gt_sflight INTO DATA(gs_sflight).
  WRITE:/ gs_sflight-airline_code, gs_sflight-connection_id,gs_sflight-airplane_price.
ENDLOOP.

PS:SELECT…AS语句需要使用新语法。

  在这个例子中,我们使用SELECT AS为CARRID和CONNID两个列定义了别名。这个别名可以在程序中被引用,这样我们就可以避免使用SFLIGHT表中的实际列名

  在程序的输出中,我们使用gs_sflight-airline_codegs_sflight-connection_id还有gs_sflight-airplane_price来引用别名,这样输出的结果中将显示别名。


动态SELECT语句

  在ABAP中,可以使用动态SELECT语句构建在运行时构建SQL语句的能力。这对于需要根据用户输入或条件动态构建SQL语句的应用程序非常有用。


  下面给出一个详细的案例进行详解:

PS:该段代码为OPEN SQL老语法格式。动态SELECT语句不推荐使用新语法,很容易报错!

DATA:gt_sflight TYPE TABLE OF sflight.
DATA:gs_sflight TYPE sflight.
DATA:gs_line(72) TYPE c.

gs_line = 'CARRID CONNID'.

SELECT  (gs_line) INTO CORRESPONDING FIELDS OF TABLE gt_sflight FROM sflight WHERE carrid =
'AC'.

LOOP AT gt_sflight INTO gs_sflight.
  WRITE:/ gs_sflight-carrid,gs_sflight-connid.
ENDLOOP.

  在这个例子中,首先,声明了一个sflight类型的结构体变量gs_sflight,和一个sflight类型的表类型gt_sflight。然后,声明了一个长度为72的字符变量gs_line。接着,将字符串'CARRID CONNID'赋值给gs_line

  紧接着,使用SELECT语句从sflight表中查询符合条件carrid = 'AC'的记录,并将其按照gs_line所指定的字段顺序,存储到表类型gt_sflight中。

  最后,通过LOOP语句遍历gt_sflight表中的每一行记录,并使用WRITE语句将每条记录的CARRID、CONNID、PRICE字段的值输出到控制台。


DISTINCT

  [DISTINCT]为OPEN SQL中SELECT语句的可选项,若选择则自动删除所查询数据的重复项!在某些场景中,我们需要对查到的数据进行去重的操作,这时候便需要加上DISTINCT可选项!


  下面给出一个详细的案例进行讲解:

DATA:GT_SFLIGHT TYPE TABLE OF SFLIGHT.
DATA:GS_SFLIGHT TYPE SFLIGHT.
DATA:GS_LINE(72) TYPE C.
 
GS_LINE = 'CARRID CONNID'.
 
SELECT DISTINCT (GS_LINE) INTO CORRESPONDING FIELDS OF TABLE GT_SFLIGHT FROM SFLIGHT WHERE CARRID = 'AC'.
 
LOOP AT GT_SFLIGHT INTO GS_SFLIGHT.
   WRITE:/ GS_SFLIGHT-CARRID,GS_SFLIGHT-CONNID.
ENDLOOP.

  在SFLIGHT数据库表中,CARRID等于‘AC’的数据有五条,使用了DISTINCT语句后查询出来的数据便只有一条了。


FOR UPDATE

   在ABAP中,SELECT SINGLE语句可以使用FOR UPDATE选项来锁定检索到的行,以便在事务期间对它们进行更新或删除操作。当使用FOR UPDATE选项时,会在数据库中为检索到的行设置锁,防止其他用户同时修改相同的数据

   下面给出一个详细的案例进行详解:

START-OF-SELECTION.

DATA: lv_name TYPE zemployee-name,
      lv_salary TYPE zemployee-salary.

* Select employee with ID = 123 and lock the row for update
SELECT SINGLE name, salary
  FROM zemployee
  WHERE id = '123'
  INTO (lv_name, lv_salary)
  FOR UPDATE.

* Update the employee's salary
lv_salary = lv_salary + 1000.

* Commit the changes
COMMIT WORK.

   在这个示例中,首先使用SELECT SINGLE语句检索ID为123的员工姓名和工资,并将该行锁定以进行更新。然后,将员工的工资增加1000,并在事务结束时提交更改。由于该行被锁定,其他用户无法同时更新相同的数据

PS:FOR UPDATE可选项一般比较少用到,读者仅仅需要对其有了解即可。


写在最后的话

  本文花费大量时间介绍了OPEN SQL中SELECT语句的详细语法,希望能帮助到各位小伙伴,码文不易,还望各位大佬们多多支持哦,你们的支持是我最大的动力!

原 创 不 易 , 还 希 望 各 位 大 佬 支 持 一 下 \\textcolorblue原创不易,还希望各位大佬支持一下

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

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

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

以上是关于「SAP ABAP」OPEN SQLGROUP BY | HAVING | ORDER BY的主要内容,如果未能解决你的问题,请参考以下文章

「SAP ABAP」OPEN SQLWHERE语句大全

「SAP ABAP」OPEN SQL的DML语句你了解多少 (附超详细案例讲解)

「SAP ABAP」你真的了解OPEN SQL的DML语句吗 (附超详细案例讲解)

第二篇SAP ABAP7.50新语法之OPEN SQL

使用 OPEN CURSOR 和 FETCH NEXT CURSOR 对 SAP 数据库表进行分块读写试读版

6.3 SAP ABAP 开放封闭原则(OCP)- 摘自 《SAP ABAP面向对象程序设计:原则模式及实践》