在外部SELECT列表(SAP ASE 16)中的子查询中使用SELECT TOP 1

时间:2015-09-28 02:15:57

标签: subquery sap sybase sqlanywhere

我有一个在Sybase SQL Anywhere 11中运行的查询,我需要在SAP Adaptive Server Enterprise 16中编译。但代码并不想在ASE中编译,说明

  

SELECT TOP不允许在子查询中使用。

以下是查询:

SELECT  a.value,
        Bcode = (SELECT TOP 1 b.code
                FROM    Btable b
                WHERE   b.value = a.value
                AND     b.deleted_flag = 'N'
                ORDER BY b.start_date DESC, b.start_time DESC),
        Bdesc = CASE
                    WHEN Bcode = 'a' THEN 'Alpha'
                    WHEN Bcode = 'b' THEN 'Beta'
                    WHEN Bcode = 'c' THEN 'Cappa'
                    WHEN Bcode = 'd' THEN 'Delta'
                    ELSE 'Epsilon'
                END,
        a.category,
        a.status,
        a.start_date,
        a.start_time
FROM    Atable a
WHERE   a.deleted_flag = 'N'
AND     a.start_date BETWEEN @a_datefrom AND @a_dateto
AND     a.end_date IS NULL
ORDER BY a.start_date`

我可以做些什么来获得相同的结果?是否需要将数据选择到临时表中,然后通过一组原子语句进行操作?提前感谢您的时间和精力。

2 个答案:

答案 0 :(得分:0)

SAP中有Native SQL feature可用于执行语句,但必须根据链接进行调整。

如果您想使用SAP SQL,我会执行以下操作:

FORM load using p_date1 type datum p_date2 type datum.
    DATA: it_atable type standard table of ty_atable,
          it_btable type standard table of ty_btable,
          wa_btable like line of it_btable
          wa_atable like line of it_atable,
          lv_index type sy-tabix.

    SELECT  value
            category
            status
            start_date
            start_time
            end_date " Include end_date to delete nulls later
    FROM    atable
    INTO CORRESPONDING FIELDS OF TABLE it_atable
    WHERE   deleted_flag = 'N'
    AND     start_date between lv_date1 and lv_date2.

    CHECK SY-SUBRC EQ 0. " No data? Do not continue.

    SELECT value code " I wouldn't get the TOP n. Just take the data and order it
    FROM    btable
    INTO CORRESPONDING FIELDS OF TABLE it_btable
    FOR ALL ENTRIES IN it_atable
    WHERE   value = it_atable-value
            deleted_flag = 'N'
    ORDER BY start_date DESC start_time DESC.

    LOOP AT it_atable INTO wa_atable.
        lv_index = sy-tabix.

        CHECK wa_atable-end_date is not initial.
* Get the first row         
        READ TABLE it_btable INTO wa_btable WITH KEY value = wa_atable. 

        IF SY-SUBRC IS INITIAL.
            CASE wa_btable-code.
                WHEN 'a'.
                    wa_atable-bdesc = 'Alpha'.
                WHEN 'b'.
                    wa_atable-bdesc = 'Beta'.
                WHEN 'c'.
                    wa_atable-bdesc = 'Cappa'.
                WHEN 'd'.
                    wa_atable-bdesc = 'Delta'.
                OTHERS
                    wa_atable-bdesc = 'Epsilon'.
            ENDCASE.
            wa_atable-bcode = wa_btable-code.
        ENDIF.

        MODIFY it_atable FROM wa_atable INDEX lv_index.
    ENDLOOP.

    DELETE it_atable WHERE end_date IS INITIAL. " Delete the null dates
ENDFORM.

我没有测试代码,因为我现在没有连接到SAP。

最后,没有" TOP n" SAP SQL中的语句。你必须使用" UP to n ROWS"。检查此link

希望它有所帮助。

答案 1 :(得分:0)

我认为您需要的是使用HAVING。

Bcode = (SELECT MIN(code)
        FROM    Btable 
        WHERE   value = a.value
        AND     deleted_flag = 'N'
        HAVING  start_date = MIN(start_date)
        AND     start_time = MIN(start_time)
        AND     deleted_flag = 'N'
        ),

可能没有必要在HAVING子句中重复deleted_flag ='N'测试。

您可能需要MIN(代码),因为Atable中每行中满足“具有最小日期和时间”的相关联接中可能有多行到Btable,并假设它们具有不同的代码,您必须MIN ()他们。

我怀疑这可能仍然不起作用,因为你有不同的日期和时间字段,而最短日期的记录可能没有最短时间。我不知道它们的类型是什么,但如果它们是DATE和TIME,那么我认为你需要将它们转换为字符串,连接并转换回DATETIME,所有这些都在一个表达式中,然后运行HAVING条件在那。否则改为使用DATETIME。