Sql 从列值为“0”的表中选择行;“最高优先权”;

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和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 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优先级从原始表中选择行

这样的选择是不可能的

在我的脑海里,我想到了这些可能性,但可能还有更多。根据你的情况,你必须找出哪一个最适合你的需要

  • 您可以选择所有内容,在其上循环并使用IF条件等创建格式

  • 如果您真的只有这4种DOC1可能性,那么您可以选择所有内容,按客户机和DOC1对内部表进行排序,然后仅通过比较客户机来删除相邻的重复项。这会起作用,因为“ITCI>ITPP>ITPS>ITPT”是按字母顺序排列的

  • 同样,如果您只有这4个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规则)
    • 如果多行
      SFLIGHT
      的CARRID和PAYMENTSUM值相同,则随机选择其中一行(经典SQL规则)
    • 它在ABAP7.52中工作,但在旧版本中可能不工作
    • 对于未来有更复杂请求的访问者,该解决方案可能很快变得不可能适应
    • 在“原生SQL”(直接使用数据库SQL)中可能有一些更简单的解决方案,比如使用
      SELECT。。。FROM(选择…
      (在ABAP SQL 7.53之前不允许)

    hi Legix,“如果我理解正确,您希望select仅为每个客户端输出一行,根据DOC1优先级从原始表中选择行。”“是的,我正在尝试这样做。你能帮我写一些代码吗?我有6种类型的doc1。我认为OP不需要MIN(DOC2),他想要的是对应于包含th的行的DOC2值
    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).