Проверьте, существует ли какой-либо элемент в списке A в списке B - PullRequest
0 голосов
/ 17 октября 2019

Я изучаю Oracle SQL на работе и ищу какое-то (идеально компактное и эффективное) условное выражение, которое оценивается как true, если какой-либо элемент в списке A появляется в списке B.

У меня есть таблицаIVS со столбцом значений CODES и таблицей POP с набором столбцов (от CDE_VAL_1 до CDE_VAL_26). Для любой строки / записи в POP каждое из полей CDE_VAL_* может содержать значение из столбца IVS.CODES или же содержать NULL. Скажем, у меня есть подмножество IVS (назовите его IVS_sub), затем я ищу способ выбрать подмножество POP, чтобы каждая выбранная запись имела некоторый код из IVS_sub.CODES в любом из CDE_VAL_* поля.

У меня есть код, который «работает», но работает слишком медленно, чтобы я мог тестировать свой код более одного или двух раз в день. Очевидно, что это слишком медленно, мне нужно иметь возможность тестировать и переписывать / исправлять код с разумным оборотом.

Это мой текущий (медленный) метод в качестве минимального примера:

SELECT DISTINCT * FROM POP 
INNER JOIN IVS 
    ON IVS.CODES IN (CDE_VAL_1, /*... pretend i listed them all here*/, CDE_VAL_26)

Обратите внимание, что фактический запрос, который я выполняю, намного сложнее, имеет пару других объединений, фильтрацию,и т.д. (при этом я уверен , что мое узкое место - это проблема, удаление соединения IVS занимает запрос от ~ 2,5 часа до ~ 10 минут).

Я также пытался:

SELECT DISTINCT * FROM POP 
INNER JOIN IVS ON (CDE_VAL_1 IN IVS.CODES
                   OR CDE_VAL_2 IN IVS.CODES
                   /* ... */
                   OR CDE_VAL_26 IN IVS.CODES)

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

Предпочтительно, я бы хотел получить что-то вроде

SELECT * FROM POP
/* other joins and stuff */
INNER JOIN IVS ON ANY_OF(CDE_VAL_1, ... ) IN IVS.CODES
WHERE /*where conditions*/

или аналогичное, где ANY_OF(...) IN ... просто заменяет любое решениеВ идеале это решение должно быть относительно компактным фрагментом с ясным смыслом.

Концептуально это просто "Если пересечение этих двух списков не пусто", но до сих пор я не видел ничего подобного.

(Примечание: мы не используем PL / SQL, а просто запросы Oracle SQL, хотя, если есть решения, требующие PL / SQL, мне было бы интересно их услышать, если бы я использовал их как боеприпасычтобы убедить моего босса обучить нас или что-то в этом роде.)

1 Ответ

0 голосов
/ 21 октября 2019

Вы можете решить свою проблему, используя unpivot. Как пример:

  with ivs as (
    select '1' codes from  dual
     union all
    select '6' codes from  dual  ),
    pop as    (
        select  1 id, '1' CDE_VAL_1, '2' CDE_VAL_2 ,'3' CDE_VAL_3 , '4' CDE_VAL_4,'5' CDE_VAL_5 from  dual
    union all
         select 2 id, '7' CDE_VAL_1, '8' CDE_VAL_2 , '9' CDE_VAL_3 , '10' CDE_VAL_4, '6' CDE_VAL_5 from  dual
    ),
    pop_unpivot as (
    select * from pop
    unpivot
       ( 
            code_value  for code_name in (CDE_VAL_1, CDE_VAL_2, CDE_VAL_3, CDE_VAL_4, CDE_VAL_5)
        )
    ),
    match as (
    select distinct pop_unpivot.id,ivs.codes  
    from pop_unpivot,ivs where pop_unpivot.code_value=ivs.codes
    )
select pop.*,ivs.* from match,pop,ivs where match.id=pop.id and match.codes=ivs.codes;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...