Sql 从列值为“0”的表中选择行;“最高优先权”;
我有一个包含DOC1、DOC2和CLIENT列的数据库表。我试图为每个客户机选择一行,其DOC1列的优先级最高,从高到低依次为:ITCI>ITPP>ITPS>ITPT 这里有一个例子 输入Sql 从列值为“0”的表中选择行;“最高优先权”;,sql,abap,opensql,sap-bw,Sql,Abap,Opensql,Sap Bw,我有一个包含DOC1、DOC2和CLIENT列的数据库表。我试图为每个客户机选择一行,其DOC1列的优先级最高,从高到低依次为:ITCI>ITPP>ITPS>ITPT 这里有一个例子 输入 DOC1 DOC2客户端 ITCI GG319 101 ITPS YB311 102 ITPT GG319 101 ITPP YB311 102 输出 目标表应该有CLIENT has unique key,我必须添加两列DOC1和DOC2,方法是取具有最高优先级的DOC1的行 CLIENT DOC2 DO
DOC1 DOC2客户端
ITCI GG319 101
ITPS YB311 102
ITPT GG319 101
ITPP YB311 102
输出
目标表应该有CLIENT has unique key,我必须添加两列DOC1和DOC2,方法是取具有最高优先级的DOC1的行
CLIENT DOC2 DOC1
101 GG319 ITCI
102 YB311 ITPP
我编写了一个select single in end例程,但出现语法错误:
Select single doc1 doc2 (W_doc1, W_doc2)
FROM /BI0/Pdoctax
WHERE client eq <RESULT_FIELDS>-client.
选择单个doc1 doc2(W_doc1,W_doc2)
FROM/BI0/Pdoctax
其中client eq-client。
如果我理解正确,您希望select仅为每个客户端输出一行,根据那些DOC1优先级从原始表中选择行
这样的选择是不可能的
在我的脑海里,我想到了这些可能性,但可能还有更多。根据你的情况,你必须找出哪一个最适合你的需要
由于从最高到最低的优先级顺序完全类似于字母顺序,您只需使用GROUP BY和MIN聚合:
SELECT client, MIN( doc2 ) AS doc2, MIN( doc1 ) AS doc1
INTO TABLE @DATA(itab)
FROM /BI0/Pdoctax
GROUP BY client.
在比较复杂的情况下,如果排序规则不是原始的,您可以使用
CASE
子句。因为您的doc1优先级值实际上是六,所以这应该可以工作
SELECT b~client,
coalesce( p1~doc1, p2~doc1, p3~doc1, p4~doc1, p5~doc1, p6~doc1 ),
coalesce( p1~doc2, p2~doc2, p3~doc2, p4~doc2, p5~doc2, p6~doc2 )
FROM /bi0/pdoctax AS b
LEFT OUTER JOIN /bi0/pdoctax AS p1
ON p1~client = b~client
AND p1~doc1 = 'ITCI'
LEFT OUTER JOIN /bi0/pdoctax AS p2
ON p2~client = b~client
AND p2~doc1 = 'ITPS'
LEFT OUTER JOIN /bi0/pdoctax AS p3
ON p3~client = b~client
AND p3~doc1 = 'ITPT'
LEFT OUTER JOIN /bi0/pdoctax AS p4
ON p4~client = b~client
AND p4~doc1 = 'ITPT'
LEFT OUTER JOIN /bi0/pdoctax AS p5
ON p4~client = b~client
AND p4~doc1 = 'P5'
LEFT OUTER JOIN /bi0/pdoctax AS p6
ON p4~client = b~client
AND p4~doc1 = 'P6'
WHERE b~client = @<result_fields>-client
INTO @DATA(ls_doctax).
选择b~客户端,
聚结(p1~doc1,p2~doc1,p3~doc1,p4~doc1,p5~doc1,p6~doc1),
聚结(p1~doc2,p2~doc2,p3~doc2,p4~doc2,p5~doc2,p6~doc2)
从/bi0/pdoctax到b
左外连接/bi0/pdoctax作为p1
在p1~客户机=b~客户机上
p1~doc1='ITCI'
左外连接/bi0/pdoctax为p2
在p2~客户机=b~客户机上
p2~doc1='ITPS'
左外连接/bi0/pdoctax为p3
在p3~客户机=b~客户机上
p3~doc1='ITPT'
左外连接/bi0/pdoctax为p4
在p4~客户机=b~客户机上
p4~doc1='ITPT'
左外连接/bi0/pdoctax作为p5
在p4~客户机=b~客户机上
p4~doc1='P5'
左外连接/bi0/pdoctax为p6
在p4~客户机=b~客户机上
p4~doc1='P6'
其中b~client=@-client
进入@DATA(ls_doctax)。
我假设您正在寻找在单个SELECT语句中实现这一点的答案,否则您可以循环:
DATA lt_priorities TYPE STANDARD TABLE OF /bi0/pdoctax-doc1.
lt_priorities = VALUE #( ( 'ITCI' ) ( 'ITPS' ) ( 'ITPT' ) ( 'ITPP' ) ( 'P500' ) ( 'P600' ) ).
SELECT b~client,
doc1,
doc2
FROM /bi0/pdoctax AS b
WHERE b~client = @<result_fields>-client
ORDER BY doc1 ASCENDING
INTO TABLE @DATA(lt_doctax).
DATA ls_doctax_filtered LIKE LINE OF lt_doctax.
LOOP AT lt_priorities ASSIGNING FIELD-SYMBOL(<fs_priority>).
READ TABLE lt_doctax ASSIGNING FIELD-SYMBOL(<fs_doctax>)
WITH KEY doc1 = <fs_priority> BINARY SEARCH.
IF sy-subrc = 0.
ls_doctax_filtered = <fs_doctax>.
* --->
EXIT.
ENDIF.
ENDLOOP.
DATA lt_优先级类型标准表/bi0/pdoctax-doc1。
lt_priorities=VALUE#(('ITCI')('ITPS')('ITPT')('ITPP')('P500')('P600'))。
选择b~客户机,
文件1,
文档2
从/bi0/pdoctax到b
其中b~client=@-client
doc1升序命令
进入表@DATA(lt_doctax)。
数据ls_doctax_像lt_doctax行一样过滤。
在lt_优先级分配字段-SYMBOL()处循环。
读取表lt_doctax赋值字段-SYMBOL()
使用doc1键=二进制搜索。
如果sy subrc=0。
ls_doctax_filtered=。
* --->
出口
恩迪夫。
结束循环。
下面是一个使用ABAP 7.52的“简单”解决方案
我为测试使用了另一个示例,这样任何人都可以使用它:我使用了任何ABAP安装都提供的演示表SFLIGHT
。如果表格为空,请运行程序SAPBC\u DATA\u GENERATOR
生成数据
正如其他人已经提到的,假设您的优先级基于字母顺序,因此可以使用聚合函数MIN
下面的代码获取SFLIGHT
的行,这些行匹配CARRID列的每个不同值(相当于您问题中的CLIENT)及其PAYMENTSUM(DOC1)列中的最小值(都在EXISTS
子查询中):
数据库表内容SFLIGHT
(通过SE16/突出显示预期结果):
内部表的内容itab
(通过调试/按预期):
关于ABAP SQL代码的注意事项:
- 对聚合结果的任何选择只能在具有之后进行,而不能在WHERE之后进行(经典SQL规则)
- 如果多行
的CARRID和PAYMENTSUM值相同,则随机选择其中一行(经典SQL规则)SFLIGHT
- 它在ABAP7.52中工作,但在旧版本中可能不工作
- 对于未来有更复杂请求的访问者,该解决方案可能很快变得不可能适应
- 在“原生SQL”(直接使用数据库SQL)中可能有一些更简单的解决方案,比如使用
(在ABAP SQL 7.53之前不允许)SELECT。。。FROM(选择…
SELECT carrid, fldate AS doc2, paymentsum AS doc1
FROM sflight AS a
WHERE EXISTS (
SELECT carrid
FROM sflight
WHERE carrid = a~carrid
GROUP BY carrid
HAVING MIN( paymentsum ) = a~paymentsum )
INTO TABLE @DATA(itab).