Eu tenho uma tabela que contém um ID na coluna um e esse ID pode ter até 30 códigos e datas diferentes associados a ele.
ID | CÓDIGO_1 | CÓDIGO_1_DATA | CÓDIGO_2 | CODE_2_DATE | CÓDIGO_3 | CÓDIGO_3_DATA
Aqui está a única maneira que consigo fazer isso, que não parece eficiente e também não captura a data:
SELECT ID, CODE_1, CODE_2, CODE_3
FROM CDHISTTBL
WHERE (ID = 'J12999' AND CODE_1 = 'AB99') or (ID = 'J12999' AND CODE_2 = 'AB99') or (ID = 'J12999' AND CODE_3 = 'AB99')
É assim que eu gostaria que o código fosse executado:
SELECT ID, CODE, CODE_DATE
FROM CDHISTTBL
WHERE ID = 'J12999' AND CODE = 'AB99'
Existe uma maneira de executar esta consulta para simplesmente retornar o ID, o código e o valor de data correspondente sem precisar verificar especificamente cada combinação de ID + código?
Você pode tentar isso. É menos digitação, mas essencialmente o mesmo:
Também não informará a data do código correspondente.
Você realmente quer uma nova tabela nos moldes abaixo (a sintaxe pode estar um pouco errada)
A partir daqui você pode encontrar o que precisa.
Com uma pequena ajuda do código que cria código para você, você pode criar uma visualização e buscar dados de maneira simples.
Dados de amostra (até "4"; não tive vontade de fazer isso para valores "30"):
Os valores de seu interesse (ID = J12999 e
CODE_X
= 'AB99') estão emCODE_1
com data igual a 15.01.2022)CODE_4
com data igual a 28.01.2023)Código que escreve código para você (na última linha, você usaria
30
em vez de,4
pois sua tabela tem 30 códigos ):Agora, copie/cole essa saÃda e use-a ao criar uma visualização (adicione a primeira linha e remova o final
union all
):É isso; o resto é trivial:
Porém, considere o que @LoztInSpace disse e redesenhe essa tabela. Não é assim que deveria ser.
Atualize para a resposta anterior: se você não conseguir normalizar a estrutura da tabela, poderá dinamizá-la com um vew ou CTE:
Para usar o
SELECT
do CTE em muitos lugares, crie-o como uma visualização para não precisar incluÃ-lo em todas as consultas que precisam dessa pesquisa.A
CodeFoundInSlot
coluna que adicionei é opcional, remova-a se o local onde o código foi encontrado nunca for importante para suas consultas.O desempenho disso pode ser pior do que algumas das outras respostas (embora não seja pior do que 30 seleções separadas); portanto, verifique se a solução tem um desempenho aceitável no tamanho/padrão dos seus dados.
Resposta anterior:
Como LoztInSpace já disse, o ideal é redesenhar para normalizar seus dados, tornando esse tipo de consulta muito mais fácil.
Com a estrutura existente você poderia fazer algo como:
Isso retornará uma linha com NULL na data se nada for encontrado, você pode remover isso usando um CTE ou repetindo a grande cláusula CASE:
Longe do ideal, mas funcionará. Novamente, reorganizar a estrutura de dados seria preferÃvel se isso estivesse ao seu alcance.
De forma mais compacta que UNION ALL e sem a necessidade de gerar SQL dinamicamente, transforme uma única linha em três linhas para que cada linha possa ser dedicada a apenas um desses pares de colunas.
No entanto, isso não terá um bom desempenho se cada um dos seus valores de ID tiver um número muito grande de valores CODE distintos, pois estes últimos não podem ser indexados. Você ainda pode indexar o ID e isso pode ser bom o suficiente.
Várias pessoas forneceram vários métodos para fazer essa transformação. Espero que a complexidade envolvida em cada um demonstre quão indesejáveis ​​são os dados não normalizados em um RDBMS. Sua melhor solução é redesenhar a tabela com a normalização adequada. Para começar, certifique-se de nunca usar grupos repetidos de colunas como esse em nenhum dos designs de seu banco de dados.