按(部分)键从表中选择特定列中具有最大值的行是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似乎不支持它们,并且无法找到任何等效的解决方案,我开始认为我别无选择,只能将子查询的数据转储到itab中。
在ABAP开发中,这种常见编程需求的最佳实践是什么?
首先,具体的要求,会给你一个更好的答案。碰巧的是,我在编写一个程序时遇到了这个问题,该程序使用3种不同的伪分组方法(同时寻找替代方法),并且所有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个查询都可以使用连接来获得相同的结果。
请在下面找到我的答案。
-
语法不支持子查询的连接:
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比较。
左连接不支持小于比较,外连接只支持EQ比较:
SELECT * FROM X AS X LEFT JOIN X AS xmax ON X -key1 = xmax-key1 AND X -key2 <如果xmax-key是INITIAL>如果xmax-key是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 <> ''.
并且至少从2008年7月7日起有效,所以在你问这个问题的时候它也是有效的。