从表中选择行,其中列值具有“最高优先级”

时间:2019-07-25 09:09:54

标签: sql abap opensql sap-bw

我有一个包含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的行来添加两列DOC1和DOC2。

CLIENT DOC2 DOC1
101   GG319 ITCI
102   YB311 ITPP

我在结束例程中编写了一个select single,但是存在语法错误:

Select single doc1  doc2 (W_doc1, W_doc2)
        FROM /BI0/Pdoctax
        WHERE  client eq <RESULT_FIELDS>-client. 

4 个答案:

答案 0 :(得分:1)

由于您的优先顺序从最高到最低完全类似于字母顺序,因此您只需要使用GROUP BY和MIN聚合:

SELECT client, MIN( doc2 ) AS doc2, MIN( doc1 ) AS doc1
INTO TABLE @DATA(itab)
FROM /BI0/Pdoctax
GROUP BY client.

在排序规则不是原始的更复杂的情况下,可以使用CASE子句。

答案 1 :(得分:0)

如果我理解这一权利,则您希望选择项每个CLIENT仅输出一行行,并根据那些DOC1优先级从原始表中选择行。

这样的选择是不可能的。

在我的头上,这些是我想出的可能性,但可能还有更多。根据您的情况,您将必须找出最适合您的需求。

  1. 您可以选择所有内容,对其进行遍历,并使用IF条件等创建格式。

  2. 如果确实只有这4种DOC1,则可以选择所有内容,按CLIENT和DOC1对内部表进行排序,然后删除仅比较CLIENT的邻接重复项。这将起作用,因为“ ITCI> ITPP> ITPS> ITPT”是按字母顺序排列的。

  3. 同样,如果您只有这4种DOC1可能性,则可以彼此选择它们,检查是否还有缺少的CLIENTS。

答案 2 :(得分:0)

由于您的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.

答案 3 :(得分:0)

这是ABAP 7.52的“简单”解决方案。

我使用了另一个示例进行测试,以便任何人都可以使用它:我使用了ABAP安装随附的演示表SFLIGHT。如果表为空,请运行程序SAPBC_DATA_GENERATOR来生成数据。

正如其他人已经提到的那样,假定您的优先级基于字母顺序,因此可以使用聚合函数MIN

下面的代码获取SFLIGHT行,这些行与CARRID列的每个不同值(相当于您的问题中的CLIENT)及其在PAYMENTSUM(DOC1)列中的最小值(都位于{{1 }}子查询):

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). 的内容(通过SE16 /预期结果突出显示): enter image description here

内部表SFLIGHT的内容(通过调试/按预期): enter image description here

关于ABAP SQL代码的说明:

  • 对聚合结果的任何选择只能在HAVING之后进行,而不能在WHERE(经典SQL规则)之后进行。
  • 如果itab的多行具有相同的CARRID和PAYMENTSUM值,则将随机选择其中一行(经典SQL规则)。
  • 它在ABAP 7.52中可用,但在较旧版本中可能无法使用。
  • 对于将来有更复杂要求的访客,该解决方案可能很快就无法适应。
  • 在“本机SQL”(直接使用数据库SQL)中可能有一些更简单的解决方案,例如使用SFLIGHT(ABAP SQL 7.53之前不允许)