Обновите подзапрос и ограничьте число строк

#sql #oracle #rownum

Вопрос:

Я написал этот запрос:

 UPDATE artpxvtemagtemp a
    SET
    origineprix = 'CEN',
    pxvente = (
        SELECT
            ap.pxvtrpublic
        FROM
            artpxvte   ap
            JOIN article    ar ON ar.idarticle = ap.idarticle
        WHERE
            ap.idarticle = a.idarticle
            AND a.unite = ap.unite
            AND ap.isdegressif = 0
            AND ap.idtarifvte = 'T00002'
            AND ap.datedebut <= pdateappli
            AND ( ap.datefin IS NULL OR pdateappli < ( ap.datefin   1 ) )
    );
 

Но иногда подзапрос дает более одного результата, поэтому обновление завершается неудачно.
Я хочу упорядочить результат и выбрать первый результат подзапроса, чтобы выполнить обновление.
Так что я делаю :

 UPDATE artpxvtemagtemp a
SET
    origineprix = 'CEN',
    pxvente = (
        SELECT
            pxvtrpublic
        FROM 
        (
        SELECT
            ap.pxvtrpublic
        FROM
            artpxvte   ap
            JOIN article    ar ON ar.idarticle = ap.idarticle
        WHERE
            ap.idarticle = a.idarticle
            AND a.unite = ap.unite
            AND ap.isdegressif = 0
            AND ap.idtarifvte = 'T00002'
            AND ap.datedebut <= pdateappli
            AND ( ap.datefin IS NULL
                    OR pdateappli < ( ap.datefin   1 ) )
        ORDER BY 
            CASE WHEN ap.datefin IS NULL THEN 0 ELSE 1 END ASC,
            ap.datefin DESC,
            ap.datedebut DESC
        )
        where rownnum <= 1
    );
 

Это не работает, потому что псевдоним a потерян, поэтому мне нужно добавить дополнительный подзапрос только для номера строки.

Ошибка SQL : ORA-00904: «A».»UNITE» : идентификатор, не соответствующий действительности 00904. 00000 — «%s: недопустимый идентификатор»

В Oracle 12C мне не нужен подзапрос для извлечения первых N-х строк, но у меня старая версия Oracle, поэтому я не могу ее использовать.

Как я могу сообщить псевдоним a ?

Ответ №1:

Вместо этого используйте агрегацию:

 pxvente = (select max(ap.pxvtrpublic) keep (dense rank first
                                            order by case when ap.datefin is null then 0 else 1 end,
                                                     ap.datefin desc,
                                                     ap.datedebut desc
                                           )
            from . . .
 

Комментарии:

1. Спасибо. Для чего нужен «макс»? Поскольку я не хочу брать максимальное значение «ap.pxvtrpublic», я просто хочу упорядочить результат по дате, выбрать первую строку и получить значение «ap.pxvtrpublic» .

2. @user2178964 . . . Это действительно keep выражение, которое по сути является «первой» функцией агрегации. Это именно то, чего ты хочешь.