Oracle SQL - вернуть несколько столбцов из подзапроса - PullRequest
0 голосов
/ 08 мая 2019

Давайте возьмем простой запрос в Oracle:

SELECT
    CASE.ID,
    CASE.TYPE,
    CASE.DATE_RAISED
FROM
    CASE
WHERE
    CASE.DATE_RAISED > '2019-01-01'

Теперь, скажем, другая таблица, EVENT, содержит несколько событий, которые могут быть связаны с каждым случаем (связанным через EVENT.CASE_ID).ИЛИ не существует вообще.Я хочу сообщить о самом раннем событии в будущем для каждого случая - или, если ничего не существует, вернуть NULL.Я могу сделать это с помощью подзапроса в предложении SELECT следующим образом:

SELECT
    CASE.ID,
    CASE.TYPE,
    CASE.DATE_RAISED,
    (
    SELECT
        MIN(EVENT.DATE)
    FROM
        EVENT
    WHERE
        EVENT.CASE_ID = CASE.ID
        AND EVENT.DATE >= CURRENT_DATE
    ) AS MIN_EVENT_DATE
FROM
    CASE
WHERE
    CASE.DATE_RAISED > '2019-01-01'

Это вернет таблицу, подобную этой:

Case ID Case Type   Date Raised Min Event Date
76      A           03/01/2019  10/05/2019
43      B           02/02/2019  [NULL]
89      A           29/01/2019  08/07/2019
90      A           04/03/2019  [NULL]
102     C           15/04/2019  20/05/2019

Обратите внимание, что если не существует никаких событийкоторые соответствуют критериям, строка все еще возвращается, но без значения.Это потому, что подзапрос находится в предложении SELECT.Это работает просто отлично.

Однако моя проблема заключается в том, что я хочу вернуть более одного столбца из таблицы EVENT, при этом сохраняя при этом возможность того, что в таблице EVENT нет совпадающих строк.,Приведенный выше код возвращает только EVENT.DATE как результат одного подзапроса в ОДИН столбец основного запроса.Но что, если я также хочу вернуть EVENT.ID или EVENT.TYPE?Все еще позволяя им иметь значение NULL (если не найдено соответствующих записей из CASE)?

Я полагаю, что я мог бы использовать несколько подзапросов в предложении SELECT: каждый возвращал только ОДИН столбец.Но это кажется ужасно неэффективным, учитывая, что каждый подзапрос будет основываться на одних и тех же критериях (СОБЫТИЕ с минимальной датой, ИД CASE которого совпадает с основным запросом, или NULL, если такие события не найдены).

Я подозреваюнекоторые изящные объединения были бы ответом - хотя я изо всех сил пытаюсь понять, какие именно.

Обратите внимание, что приведенные выше примеры - это значительно упрощенные версии моего реального кода, который уже содержит несколько объединений в «старом стиле».«Формат Oracle, например:

WHERE
    CASE.ID(+) = EVENT.CASE_ID

Есть причины, почему это так - поэтому просьба к любому, кто ответит на этот вопрос, пожалуйста, продемонстрируйте какие-нибудь решения в этом стиле кодирования, так как мой SQL не далекодостаточно продвинутый, чтобы иметь возможность повторно учитывать «более новый» стиль, включающий в существующий код.

Ответы [ 2 ]

3 голосов
/ 08 мая 2019

Вы можете использовать join и функции окна.Например:

select c.*, e.*
from c left join
     (select e.*,
             row_number() over (partition by e.case_id order by e.date desc) as seqnum
      from events e
     ) e
     on e.case_id = c.id and e.seqnum = 1;
where c.date_raised > date '2019-01-01';  -- assuming the value is a date
1 голос
/ 08 мая 2019

Это то, что вы имеете в виду?Я просто переписал ответ Гордона со старым синтаксисом соединения Oracle и вашим стилем кода.

SELECT
    CASE.ID,
    CASE.TYPE,
    CASE.DATE_RAISED,
    MIN_E.DATE AS MIN_EVENT_DATE
FROM
    CASE,
    (SELECT EVENT.*,
        ROW_NUMBER() OVER (PARTITION BY EVENT.CASE_ID ORDER BY EVENT.DATE DESC) AS SEQNUM
        FROM
            EVENT
        WHERE 
            EVENT.DATE >= CURRENT_DATE
    ) MIN_E
WHERE
    CASE.DATE_RAISED > DATE '2019-01-01'
    AND MIN_E.CASE_ID (+) = CASE.ID
    AND MIN_E.SEQNUM (+) = 1;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...