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

问题描述 投票:0回答:2

我的查询在 Sybase SQL Anywhere 11 中运行。我需要在 SAP Adaptive Server Enterprise 16 中编译。代码无法在 ASE 中编译:

`SELECT TOP` is not allowed in a subquery.
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`

我该怎么做才能得到相同的结果?

是否需要将数据选择到临时表中,然后通过一组原子语句进行操作?

subquery sybase sqlanywhere
2个回答
0
投票

SAP 中有一个本机 SQL 功能,您可以使用它来执行语句,但必须根据链接进行调整。

如果您想使用 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。

最后,SAP SQL 中没有“TOP n”语句。您必须使用“UP TO n ROWS”。检查这个链接

希望有帮助。


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(code),因为对于 Atable 中的每一行,与 Btable 的关联联接中可能有不止一行满足“具有最小日期和时间”的要求,并且假设它们具有不同的代码,您必须 MIN()他们。

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

© www.soinside.com 2019 - 2024. All rights reserved.