[英]Select row from table where column value has "highest priority"
我有一个包含 DOC1、DOC2 和 CLIENT 列的数据库表。 我试图为每个 CLIENT 选择一行,其 DOC1 列根据以下顺序具有最高优先级,从最高到最低优先级:ITCI > ITPP > ITPS > ITPT。
这是一个例子。
输入
DOC1 DOC2 CLIENT
ITCI GG319 101
ITPS YB311 102
ITPT GG319 101
ITPP YB311 102
输出
目标表应该有 CLIENT 具有唯一键,我必须添加两列 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.
由于您从最高到最低的优先级顺序完全类似于字母顺序,您只需要使用 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优先从原始表行。
这样的选择是不可能的。
在我的脑海中,这些是我想出的可能性,但可能还有更多。 根据您的情况,您必须确定哪一种最适合您的需求。
您可以选择所有内容,对其进行循环并使用 IF 条件等创建您的格式。
如果您真的只有这 4 个 DOC1 可能性,您可以选择所有内容,按 CLIENT 和 DOC1 对内部表进行排序,然后删除仅比较 CLIENT 的相邻重复项。 这是可行的,因为“ITCI >ITPP >ITPS>ITPT”是按字母顺序排列的。
同样,如果您只有这 4 个 DOC1 可能性,那么您可以依次选择它们,检查是否仍然缺少 CLIENTS。
由于您的 doc1 优先级值实际上是 6,所以这应该有效。
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).
我假设您正在寻找在单个 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.
这是 ABAP 7.52 的“简单”解决方案。
我在测试中使用了另一个示例,以便任何人都可以使用它:我使用了随任何 ABAP 安装提供的演示表SFLIGHT
。 如果表为空,则运行程序SAPBC_DATA_GENERATOR
以生成数据。
正如其他人已经提到的,假设您的优先级是基于字母顺序的,因此可以使用聚合函数MIN
。
下面的代码获取匹配列 CARRID 的每个不同值的SFLIGHT
行(相当于您问题中的 CLIENT)及其在 PAYMENTSUM (DOC1) 列中的最小值(均在EXISTS
子查询中):
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).
数据库表SFLIGHT
内容(通过 SE16/预期结果突出显示):
关于 ABAP SQL 代码的注意事项:
SFLIGHT
几行具有相同的 CARRID 和 PAYMENTSUM 值,则随机选择其中一行(经典 SQL 规则)。SELECT ... FROM ( SELECT ... )
(不允许到 ABAP SQL 7.53)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.