SQL выбрать в списке A, но создать строку, даже если нет в списке A - PullRequest
0 голосов
/ 02 июля 2018

Я пытался найти решения, но не смог найти ни одного. Пожалуйста, укажите правильное направление, если дубликат.

[Проблема]
Я хочу запросить список идентификаторов пользователей (('hunter1', 'hunter2', 'hunter3')) и проверить, согласились ли они с нашей политикой конфиденциальности.
Однако здесь есть одна загвоздка - , даже если userID отсутствует в нашей базе данных, мне нужна строка с этим ID пользователя с «N» для статуса соглашения о политике .

[КАК ЕСТЬ: текущий запрос]

Объяснение запроса: для одного идентификатора пользователя может быть несколько записей, так как этот пользователь мог присоединиться, уйти и снова присоединиться. Проще говоря, этот запрос возвращает идентификатор пользователя и его статус, где этот идентификатор пользователя имеет самый высокий порядковый номер, если этот идентификатор пользователя можно найти несколько раз.

SELECT
    userID,
    policyAgreementStatus
FROM
    MEMBERTABLE m
WHERE
    userNoSeq IN (
        SELECT
            MAX(userNoSeq)
        FROM
            MEMBERTABLE
        WHERE
            m.userID = MEMBERTABLE.userID AND MEMBERTABLE.userID IN 
                 ('hunter1', 'hunter2', ...)
    )
ORDER BY userNoSeq;

Приведенный выше запрос вернет что-то похожее на приведенное ниже, если 'hunter1' не существует в таблице.

userID      policyAgreementStatus
-----------------------------------
hunter2             Y
hunter3             N
...

[TO-BE]

Я хочу получить результат, который вернет:

userID      policyAgreementStatus
-----------------------------------
hunter1             N
hunter2             Y
hunter3             N

даже когда hunter1 не было на столе.

Самый простой способ, который я могу придумать, - создать временную таблицу или использовать коллекцию PL / SQL и объединить ее с исходной таблицей.
Однако я работаю с базой данных только для чтения, поэтому это невозможно.
Любые идеи будут полезны. Спасибо.

Ответы [ 3 ]

0 голосов
/ 02 июля 2018

Вы можете использовать LEFT внешнее соединение и MAX аналитическую функцию. CTE содержит все идентификаторы.

with h(userID) as
(
  select 'hunter1' from dual union all 
  select 'hunter2' from dual union all 
  select 'hunter3' from dual 
)
SELECT userID,
    COALESCE(policyAgreementStatus,'N') AS policyAgreementStatus
FROM
( SELECT
    h.userID,
    m.userNoSeq,
    m.policyAgreementStatus,
    COALESCE (
        MAX(m.userNoSeq) OVER (partition by h.userID ),
        0
    ) AS max_userNoSeq
FROM
    h 
LEFT OUTER JOIN
    MEMBERTABLE m
ON m.userID = h.userID
    ) WHERE max_userNoSeq IN ( userNoSeq,0) ;
0 голосов
/ 02 июля 2018

Я бы сделал это как:

select m.userid,
       coalesce(max(mt.policyAgreementStatus) keep (dense_rank first order by userNoSeq desc),
                'N'
               ) as policyAgreementStatus
from (select 'hunter1' as userid from dual union all 
      select 'hunter2' from dual union all 
      select 'hunter3' from dual 
     ) m left join
     membertable mt
     on mt.userid = m.userid
group by m.userid;

Вы можете получить самый последний policyAgreementStatus, используя синтаксис keep. Я обнаружил, что это достаточно эффективно в Oracle.

0 голосов
/ 02 июля 2018

Вам не нужно создавать объекты для использования коллекции, есть несколько встроенных. Например, вы можете предоставить свой список идентификаторов в виде ODCIVarchar2LIst, расширить его на отдельные элементы, а затем присоединить к реальной таблице слева:

WITH userIDs (userID) AS (
    SELECT
        column_value
    FROM
        TABLE(SYS.ODCIVARCHAR2LIST('hunter1', 'hunter2', 'hunter3'))
)
SELECT
    u.userID,
    COALESCE (
        MAX(m.policyAgreementStatus) KEEP (DENSE_RANK LAST ORDER BY m.userNoSeq),
        'N'
    ) AS policyAgreementStatus
FROM
    userIDs u
LEFT JOIN
    MEMBERTABLE m
ON
    m.userID = u.userID
GROUP BY
    u.userID
ORDER BY userID;

coalesce() предоставляет значение N по умолчанию, когда нет совпадения, так как левое соединение оставит этот ноль. Я переключился с вашего дополнительного выбора на использование max ... keep dense_rank last, так как он немного закорочен, но ваш исходный запрос все равно будет работать.

Возможно, у вас уже есть собственные типы коллекций, и то, как вы реализуете, зависит от того, откуда поступает список значений и как он (или может быть) предоставлен в запрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...