运行-动态 order-by 子句的时间错误(静态等效子句有效)
Run-time error for dynamic order-by clause (static equivalent clause works)
问题是除了 abap 中的硬编码排序子句之外,是否还有任何其他检查会触发动态排序子句。
我在 abap 中写了一个 sql 语句。该语句汇总了特定年份的条目数。然后它根据条目的类型对计数进行分组。
之后我尝试进行动态排序。由于某种原因,这会导致错误:"The parser produced the error: The expression that contains IN_YEAR is not a GROUP-BY expression."
问题是 order-by 子句在对排序条件进行硬编码时起作用。当我尝试动态执行时,它没有。
但我必须动态地进行排序,因为稍后排序标准将通过 oData (it_order) 来自前端。
DATA: lv_cYear TYPE NUMC4,
lv_lYear TYPE NUMC4,
lv_2YearsAgo TYPE NUMC4,
lv_order_by TYPE string.
GET TIME.
lv_cYear = sy-datum+0(4).
LV_LYEAR = LV_CYEAR - 1.
LV_2YEARSAGO = LV_CYEAR - 2.
*later lv_order_by should be filled dynamically
lv_order_by = 'RRC2019 DESCENDING, RRC2018 DESCENDING'.
SELECT
type_name AS type,
SUM( CASE WHEN in_year eq @lv_cYear THEN record_count END ) AS RRC2019,
SUM( CASE WHEN in_year eq @lv_lyear THEN record_count END ) AS RRC2018,
SUM( CASE WHEN in_year eq @LV_2YEARSAGO THEN record_count END ) AS RRC2017
FROM entryTable
GROUP BY type_name
HAVING SUM( CASE WHEN in_year eq @lv_cYear THEN record_count END ) IN @ls_in_2019_range-select_options
AND SUM( CASE WHEN in_year eq @lv_lyear THEN record_count END ) IN @ls_in_2018_range-select_options
AND SUM( CASE WHEN in_year eq @LV_2YEARSAGO THEN record_count END ) IN @ls_in_2017_range-select_options
ORDER BY (lv_order_by)
INTO CORRESPONDING FIELDS OF TABLE @et_entityset.
如果您尝试 运行 这会发生错误 "The parser produced the error: The expression that contains IN_YEAR is not a GROUP-BY expression"。
如果您将 "ORDER BY (lv_order_by)" 替换为 "ORDER BY RRC2019 DESCENDING, RRC2018 DESCENDING",它就可以正常工作。
我只是让自己准备了一个可编译的工作示例,它似乎与您所写的相反。我唯一改变的是 INTO TABLE
或(在你的情况下)INTO CORRESPONDING FIELDS OF TABLE @et_entityset
.
的位置
以下示例编译没有问题,也不会生成任何运行时异常。
REPORT YYY.
DATA: lv_cYear TYPE NUMC4,
lv_lYear TYPE NUMC4,
lv_2YearsAgo TYPE NUMC4,
lv_order_by TYPE string,
ls_in_2019_range TYPE RANGE OF cosp-wtg001,
ls_in_2018_range TYPE RANGE OF cosp-wtg001,
ls_in_2017_range TYPE RANGE OF cosp-wtg001.
GET TIME.
lv_cYear = sy-datum+0(4).
LV_LYEAR = LV_CYEAR - 1.
LV_2YEARSAGO = LV_CYEAR - 2.
*later lv_order_by should be filled dynamically
lv_order_by = 'RRC2019 DESCENDING, RRC2018 DESCENDING'.
SELECT
lednr AS type,
SUM( CASE WHEN GJAHR eq @lv_cYear THEN wtg001 END ) AS RRC2019,
SUM( CASE WHEN GJAHR eq @lv_lyear THEN wtg001 END ) AS RRC2018,
SUM( CASE WHEN GJAHR eq @LV_2YEARSAGO THEN wtg001 END ) AS RRC2017
FROM cosp
INTO TABLE @DATA(et_entityset)
GROUP BY lednr
HAVING SUM( CASE WHEN gjahr eq @lv_cYear THEN wtg001 END ) IN @ls_in_2019_range
AND SUM( CASE WHEN gjahr eq @lv_lyear THEN wtg001 END ) IN @ls_in_2018_range
AND SUM( CASE WHEN gjahr eq @LV_2YEARSAGO THEN wtg001 END ) IN @ls_in_2017_range
ORDER BY (lv_order_by).
BREAK-POINT.
这是一个在所有最新的基于 ABAP 的系统上编译的示例(使用 SAPBC_DATA_GENERATOR 程序来填充 SFLIGHT table):
DATA: dummy_price TYPE sflight-price.
SELECT-OPTIONS sum_y1 FOR dummy_price DEFAULT 0 TO 99999.
SELECT-OPTIONS sum_y2 FOR dummy_price DEFAULT 0 TO 99999.
SELECT substring( fldate, 1, 4 ) AS year,
MIN( fldate ) AS low,
MAX( fldate ) AS high
FROM sflight
GROUP BY substring( fldate, 1, 4 )
ORDER BY year
INTO TABLE @DATA(y).
ASSERT lines( y ) >= 2.
SELECT carrid,
SUM( CASE WHEN fldate BETWEEN @( y[ 1 ]-low ) AND @( y[ 1 ]-high ) THEN price END ) AS sum_year1,
SUM( CASE WHEN fldate BETWEEN @( y[ 2 ]-low ) AND @( y[ 2 ]-high ) THEN price END ) AS sum_year2
FROM sflight
GROUP BY carrid
HAVING SUM( CASE WHEN fldate BETWEEN @( y[ 1 ]-low ) AND @( y[ 1 ]-high ) THEN price END ) IN @sum_y1[]
AND SUM( CASE WHEN fldate BETWEEN @( y[ 2 ]-low ) AND @( y[ 2 ]-high ) THEN price END ) IN @sum_y2[]
ORDER BY SUM_YEAR1 DESCENDING, SUM_YEAR2 DESCENDING " <=== this works
""""ORDER BY ('SUM_YEAR1 DESCENDING, SUM_YEAR2 DESCENDING') " <=== uncomment for short dump
INTO TABLE @DATA(sflights).
LOOP AT sflights ASSIGNING FIELD-SYMBOL(<sflight>).
WRITE : / <sflight>-carrid, <sflight>-sum_year1, <sflight>-sum_year2.
ENDLOOP.
在以下 2 个系统上,我重现了该行为(它使用静态 ORDER BY 子句,短转储使用动态 ORDER BY 子句):
- 带有 SYBASE ASE 的开发人员版本 7.52 SP 1
- S/4HANA 使用 ABAP 7.52 SP 0
毫无疑问,某处存在错误,但我找不到 SAP 注释来更正该问题。那最好在 SAP 支持处开票。
我使用了@Jagger 的程序并验证它在 7.50 中工作并且从 7.51 开始中断。
这应该是一个错误。
更新:
请申请备注 2753729
问题是除了 abap 中的硬编码排序子句之外,是否还有任何其他检查会触发动态排序子句。
我在 abap 中写了一个 sql 语句。该语句汇总了特定年份的条目数。然后它根据条目的类型对计数进行分组。 之后我尝试进行动态排序。由于某种原因,这会导致错误:"The parser produced the error: The expression that contains IN_YEAR is not a GROUP-BY expression."
问题是 order-by 子句在对排序条件进行硬编码时起作用。当我尝试动态执行时,它没有。
但我必须动态地进行排序,因为稍后排序标准将通过 oData (it_order) 来自前端。
DATA: lv_cYear TYPE NUMC4,
lv_lYear TYPE NUMC4,
lv_2YearsAgo TYPE NUMC4,
lv_order_by TYPE string.
GET TIME.
lv_cYear = sy-datum+0(4).
LV_LYEAR = LV_CYEAR - 1.
LV_2YEARSAGO = LV_CYEAR - 2.
*later lv_order_by should be filled dynamically
lv_order_by = 'RRC2019 DESCENDING, RRC2018 DESCENDING'.
SELECT
type_name AS type,
SUM( CASE WHEN in_year eq @lv_cYear THEN record_count END ) AS RRC2019,
SUM( CASE WHEN in_year eq @lv_lyear THEN record_count END ) AS RRC2018,
SUM( CASE WHEN in_year eq @LV_2YEARSAGO THEN record_count END ) AS RRC2017
FROM entryTable
GROUP BY type_name
HAVING SUM( CASE WHEN in_year eq @lv_cYear THEN record_count END ) IN @ls_in_2019_range-select_options
AND SUM( CASE WHEN in_year eq @lv_lyear THEN record_count END ) IN @ls_in_2018_range-select_options
AND SUM( CASE WHEN in_year eq @LV_2YEARSAGO THEN record_count END ) IN @ls_in_2017_range-select_options
ORDER BY (lv_order_by)
INTO CORRESPONDING FIELDS OF TABLE @et_entityset.
如果您尝试 运行 这会发生错误 "The parser produced the error: The expression that contains IN_YEAR is not a GROUP-BY expression"。
如果您将 "ORDER BY (lv_order_by)" 替换为 "ORDER BY RRC2019 DESCENDING, RRC2018 DESCENDING",它就可以正常工作。
我只是让自己准备了一个可编译的工作示例,它似乎与您所写的相反。我唯一改变的是 INTO TABLE
或(在你的情况下)INTO CORRESPONDING FIELDS OF TABLE @et_entityset
.
以下示例编译没有问题,也不会生成任何运行时异常。
REPORT YYY.
DATA: lv_cYear TYPE NUMC4,
lv_lYear TYPE NUMC4,
lv_2YearsAgo TYPE NUMC4,
lv_order_by TYPE string,
ls_in_2019_range TYPE RANGE OF cosp-wtg001,
ls_in_2018_range TYPE RANGE OF cosp-wtg001,
ls_in_2017_range TYPE RANGE OF cosp-wtg001.
GET TIME.
lv_cYear = sy-datum+0(4).
LV_LYEAR = LV_CYEAR - 1.
LV_2YEARSAGO = LV_CYEAR - 2.
*later lv_order_by should be filled dynamically
lv_order_by = 'RRC2019 DESCENDING, RRC2018 DESCENDING'.
SELECT
lednr AS type,
SUM( CASE WHEN GJAHR eq @lv_cYear THEN wtg001 END ) AS RRC2019,
SUM( CASE WHEN GJAHR eq @lv_lyear THEN wtg001 END ) AS RRC2018,
SUM( CASE WHEN GJAHR eq @LV_2YEARSAGO THEN wtg001 END ) AS RRC2017
FROM cosp
INTO TABLE @DATA(et_entityset)
GROUP BY lednr
HAVING SUM( CASE WHEN gjahr eq @lv_cYear THEN wtg001 END ) IN @ls_in_2019_range
AND SUM( CASE WHEN gjahr eq @lv_lyear THEN wtg001 END ) IN @ls_in_2018_range
AND SUM( CASE WHEN gjahr eq @LV_2YEARSAGO THEN wtg001 END ) IN @ls_in_2017_range
ORDER BY (lv_order_by).
BREAK-POINT.
这是一个在所有最新的基于 ABAP 的系统上编译的示例(使用 SAPBC_DATA_GENERATOR 程序来填充 SFLIGHT table):
DATA: dummy_price TYPE sflight-price.
SELECT-OPTIONS sum_y1 FOR dummy_price DEFAULT 0 TO 99999.
SELECT-OPTIONS sum_y2 FOR dummy_price DEFAULT 0 TO 99999.
SELECT substring( fldate, 1, 4 ) AS year,
MIN( fldate ) AS low,
MAX( fldate ) AS high
FROM sflight
GROUP BY substring( fldate, 1, 4 )
ORDER BY year
INTO TABLE @DATA(y).
ASSERT lines( y ) >= 2.
SELECT carrid,
SUM( CASE WHEN fldate BETWEEN @( y[ 1 ]-low ) AND @( y[ 1 ]-high ) THEN price END ) AS sum_year1,
SUM( CASE WHEN fldate BETWEEN @( y[ 2 ]-low ) AND @( y[ 2 ]-high ) THEN price END ) AS sum_year2
FROM sflight
GROUP BY carrid
HAVING SUM( CASE WHEN fldate BETWEEN @( y[ 1 ]-low ) AND @( y[ 1 ]-high ) THEN price END ) IN @sum_y1[]
AND SUM( CASE WHEN fldate BETWEEN @( y[ 2 ]-low ) AND @( y[ 2 ]-high ) THEN price END ) IN @sum_y2[]
ORDER BY SUM_YEAR1 DESCENDING, SUM_YEAR2 DESCENDING " <=== this works
""""ORDER BY ('SUM_YEAR1 DESCENDING, SUM_YEAR2 DESCENDING') " <=== uncomment for short dump
INTO TABLE @DATA(sflights).
LOOP AT sflights ASSIGNING FIELD-SYMBOL(<sflight>).
WRITE : / <sflight>-carrid, <sflight>-sum_year1, <sflight>-sum_year2.
ENDLOOP.
在以下 2 个系统上,我重现了该行为(它使用静态 ORDER BY 子句,短转储使用动态 ORDER BY 子句):
- 带有 SYBASE ASE 的开发人员版本 7.52 SP 1
- S/4HANA 使用 ABAP 7.52 SP 0
毫无疑问,某处存在错误,但我找不到 SAP 注释来更正该问题。那最好在 SAP 支持处开票。
我使用了@Jagger 的程序并验证它在 7.50 中工作并且从 7.51 开始中断。
这应该是一个错误。
更新: 请申请备注 2753729