Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Tabela de consulta com lista diferente de variáveis ​​usando como


Se entendi bem sua necessidade, esse pode ser um caminho.

Digamos que você tenha uma tabela como esta:
create table yourTable(setid, codes, messagedescr) as ( 
  select 1,       'A, B, C, D',  'You can login' from dual union all
  select 2,       'B, C, D'   ,  'You can login for one day' from dual union all
  select 3,       'A, C, E'   ,  'You can login but update your profile' from dual union all
  select 4,       'B, C, E, F',  'You cannot login' from dual
).

Este pode ser um caminho:
with inputData(codes) as (
    select listagg(trim (regexp_substr(input_codes, '[^,]+', 1, level))) within group ( order by trim (regexp_substr(input_codes, '[^,]+', 1, level)))
    from ( select 'A, D, C, B' as input_codes from dual )  /* the input string */
    CONNECT BY instr(input_codes, ',', 1, level - 1) > 0
)    
select *
from inputData 
    inner join (
                select listagg(trim (regexp_substr(codes, '[^,]+', 1, level)))
                         within group ( order by trim (regexp_substr(codes, '[^,]+', 1, level))) as codes,
                        messagedescr
                from yourTable  
                CONNECT BY instr(codes, ',', 1, level - 1) > 0
                  and prior setId = setId
                  and prior sys_guid() is not null
                group by setId, messagedescr
               )
      using (codes)

A ideia aqui é dividir sua string de entrada em várias linhas e, em seguida, agregar as linhas resultantes em ordem alfabética, aplicar a mesma ordem nos valores da tabela e verificar se as strings ordenadas são iguais.

Esta parte é usada para dividir, ordenar e agregar os valores de entrada, para que o resultado seja uma string ordenada:
select listagg(trim (regexp_substr(input_codes, '[^,]+', 1, level))) within group ( order by trim (regexp_substr(input_codes, '[^,]+', 1, level)))
    from ( select 'A, D, C, B' as input_codes from dual )  /* the input string */
    CONNECT BY instr(input_codes, ',', 1, level - 1) > 0

dá:
ABCD

Esta parte é usada para fazer o mesmo em sua mesa:
select listagg(trim (regexp_substr(codes, '[^,]+', 1, level)))
         within group ( order by trim (regexp_substr(codes, '[^,]+', 1, level))) as codes,
        messagedescr
from yourTable  
CONNECT BY instr(codes, ',', 1, level - 1) > 0
  and prior setId = setId
  and prior sys_guid() is not null
group by setId, messagedescr  

dá:
CODES      MESSAGEDESCR
---------- -------------------------------------
ABCD       You can login
BCD        You can login for one day
ACE        You can login but update your profile
BCEF       You cannot login

A junção entre esses resultados parciais é bastante direta e simplesmente verifica se existe um valor (ordenado) em sua tabela que corresponde à string de entrada (ordenada).