2

通过(部分)键从表中选择特定列中具有最大值的行是 SQL 中的常见任务。这个问题有一些很好的答案,涵盖了各种方法。不幸的是,我正在努力在我的 ABAP 程序中复制它。

似乎不支持任何常用方法:

  • 语法不支持加入子查询:SELECT * FROM X as x INNER JOIN ( SELECT ... ) AS y
  • 据我所知,语法不支持将 IN 用于复合键:SELECT * FROM X WHERE (key1, key2) IN ( SELECT key1 key2 FROM ... )
  • 不支持使用小于比较的左连接自身,外连接仅支持 EQ 比较:SELECT * FROM X AS x LEFT JOIN X as xmax ON x-key1 = xmax-key1 AND x-key2 < xmax-key2 WHERE xmax-key IS INITIAL

在依次尝试了这些解决方案中的每一个之后,却发现 ABAP 似乎不支持它们并且无法找到任何等价物,我开始认为我别无选择,只能将子查询的数据转储到伊塔布。

ABAP 开发中这种常见的编程要求的最佳实践是什么?

4

3 回答 3

3

首先,具体的要求,会给你一个更好的答案。碰巧我在开发一个程序时遇到了这个问题,该程序使用 3 种不同的伪分组方法(在寻找替代方法时),并且 ALL 3 可用于回答您的问题,具体取决于您需要做什么。我相信还有更多的方法可以做到这一点。

例如,您可以通过简单地选择 max( your_field ) 并按某些字段分组来提取组内的最大值,如果这就是您所需要的。

select bname, nation, max( date_from ) from adrp group by bname, nation. "selects highest "from" date for each bname

如果您需要在查询中使用该最大值作为过滤条件,您可以通过使用子查询和max在子查询中执行伪分组来做到这一点(注意我如何将 BNAME 检查移到子查询中,其中意味着我不必使用in (subquery)加法检查这两个字段):

select ... from adrp as b_adrp "Pulls the latest person info for a user (some conditions are missing, but this is a part of an actual query)
where b_adrp~date_from in (
    select max( date_from ) "Highest date_from where both dates are valid
         from adrp  where persnumber = b_adrp~persnumber and nation = b_adrp~nation and date_from <= @sy-datum )

上面的查询允许您选择从基本查询中选择所有用户信息,并且(第一个查询只允许获取聚合和分组数据)。

最后,如果您需要基于复合键进行检查并将其与多个聚合函数结果进行比较,那么实现将在很大程度上取决于您的要求的具体情况(并且由于您的问题没有,我将提供一个通用的)。最简单的选择是以完全相同的方式使用exists/not exists而不是并形成子查询以检查特定键或条件的存在而不是拉列表(如果必须,您可以嵌套子查询):in (subquery)

 select * from bkpf where exists ( select 1 from bkpf as b where belnr = bkpf~belnr and gjahr = bkpf~gjahr group by belnr, gjahr having max( budat ) = bkpf~budat ) "Took an available example, that I had in testing program.

所有 3 个查询都将为您提供组内列的最大值,事实上,所有 3 个查询都可以使用连接来获得相同的结果。

于 2018-05-29T09:59:39.600 回答
0

请在您的问题下方找到我的答案。

  • 语法不支持加入子查询:SELECT * FROM X as x INNER JOIN ( SELECT ... ) AS y

    将子查询放在您的 where 条件中应该可以完成工作SELECT * FROM X AS x INNER JOIN Y AS y ON x~a = y~b WHERE ( SELECT * FROM y WHERE ... )

  • 据我所知,语法不支持将 IN 用于复合键:SELECT * FROM X WHERE (key1, key2) IN ( SELECT key1 key2 FROM ... )

    您必须拆分 WHERE 子句:SELECT * FROM X WHERE key1 IN ( SELECT key1 FROM y ) AND key2 IN ( SELECT key2 FROM y )

  • 不支持使用小于比较的左连接自身,外连接仅支持 EQ 比较。

    是的,目前就是这样。

于 2014-08-21T09:44:40.187 回答
0

不支持使用小于比较的左连接自身,外连接仅支持 EQ 比较:

SELECT * FROM X AS x LEFT JOIN X as xmax ON x-key1 = xmax-key1 AND x-key2 < xmax-key2 WHERE xmax-key IS INITIAL

这不是真的。此 SELECT 完全有效:

SELECT b1~budat
  INTO TABLE lt_bkpf
  FROM bkpf AS b1
  LEFT JOIN bkpf AS b2
    ON b2~belnr < b1~belnr
 WHERE b1~bukrs <> ''.

并且至少自 7.40 SP08, 自July 2013以来有效,因此在您问这个问题时它也是有效的。

于 2020-04-10T15:07:38.153 回答