Preciso implementar a seguinte consulta no SQL Server:
select *
from table1
WHERE (CM_PLAN_ID,Individual_ID)
IN
(
Select CM_PLAN_ID, Individual_ID
From CRM_VCM_CURRENT_LEAD_STATUS
Where Lead_Key = :_Lead_Key
)
Mas a cláusula WHERE..IN permite apenas 1 coluna. Como posso comparar 2 ou mais colunas com outro SELECT interno?
sql-server
ala
fonte
fonte
Respostas:
Você pode criar uma tabela derivada da subconsulta e associar table1 a esta tabela derivada:
fonte
Você desejará usar a sintaxe WHERE EXISTS.
fonte
AVISO SOBRE SOLUÇÕES:
MUITAS SOLUÇÕES EXISTENTES DARÃO SAÍDA ERRADA SE AS LINHAS NÃO SÃO ÚNICAS
Se você é a única pessoa que cria tabelas, isso pode não ser relevante, mas várias soluções fornecerão um número diferente de linhas de saída do código em questão, quando uma das tabelas não puder conter linhas exclusivas.
AVISO SOBRE DECLARAÇÃO DE PROBLEMA:
EM VÁRIAS COLUNAS NÃO EXISTE, PENSE CUIDADOSAMENTE O QUE VOCÊ QUER
Quando vejo uma entrada com duas colunas, consigo imaginar duas coisas:
O cenário 1 é bastante trivial, basta usar duas instruções IN.
De acordo com a maioria das respostas existentes, forneço aqui uma visão geral das abordagens mencionadas e adicionais para o Cenário 2 (e um breve julgamento):
EXISTS (Seguro, recomendado para SQL Server)
Conforme fornecido por @mrdenny, EXISTS soa exatamente como o que você está procurando, eis o exemplo dele:
ESQUERDA SEMI JOIN (Seguro, recomendado para dialetos que o suportam)
Essa é uma maneira muito concisa de ingressar, mas infelizmente a maioria dos dialetos SQL, incluindo o SQL Server, atualmente não o suporta.
Várias instruções IN (seguras, mas cuidado com a duplicação de código)
Como mencionado pelo @cataclysm, usar duas instruções IN também pode ajudar, talvez até supere as outras soluções. No entanto, você deve ter muito cuidado com a duplicação de código. Se você desejar selecionar uma tabela diferente ou alterar a instrução where, é um risco aumentado que você crie inconsistências em sua lógica.
Solução básica
Solução sem duplicação de código (acredito que isso não funcione em consultas regulares do SQL Server)
INNER JOIN (tecnicamente, isso pode ser feito com segurança, mas muitas vezes isso não é feito)
A razão pela qual eu não recomendo o uso de uma junção interna como filtro, é porque, na prática, as pessoas geralmente deixam duplicatas na tabela correta, causando duplicatas na tabela esquerda. E, para piorar a situação, às vezes eles diferenciam o resultado final, enquanto a tabela esquerda pode não precisar ser exclusiva (ou não exclusiva nas colunas que você selecionar). Além disso, oferece a chance de realmente selecionar uma coluna que não existe na tabela esquerda.
Erros mais comuns:
CONCATENAÇÃO DE COLUNAS COM SEPARADOR (Desempenho não muito seguro, horrível)
O problema funcional é que, se você usar um separador que pode ocorrer em uma coluna, fica complicado garantir que o resultado seja 100% exato. O problema técnico é que esse método geralmente gera conversões de tipo e ignora completamente os índices, resultando em um desempenho possivelmente horrível. Apesar desses problemas, tenho que admitir que às vezes ainda o uso para consultas ad-hoc em pequenos conjuntos de dados.
Observe que, se suas colunas forem numéricas, alguns dialetos SQL exigirão que você as converta em cadeias primeiro. Acredito que o SQL Server fará isso automaticamente.
Para finalizar: Como de costume, existem muitas maneiras de fazer isso no SQL, usar opções seguras evitará surpresas e economizará tempo e dinheiro a longo prazo.
fonte
Nota:
Oracle ignora as linhas em que uma ou mais das colunas selecionadas são NULL. Nesses casos, você provavelmente deseja usar o NVL -Funktion para mapear NULL para um valor especial (que não deve estar nos valores);
fonte
where (colA,colB) in (... some list of tuples...)
mas não tenho certeza do que outros bancos de dados fazem o mesmo. Eu estaria interessado em saber.Uma simples cláusula EXISTS é a mais limpa
Se você tiver várias linhas na correlação, um JOIN fornecerá várias linhas na saída, portanto, você precisará de distintas. O que geralmente torna os EXISTS mais eficientes.
Nota
SELECT *
com um JOIN também incluiria colunas das tabelas de limitação de linhasfonte
Por que usar WHERE EXISTS ou DERIVED TABLES quando você pode apenas fazer uma junção interna normal:
Se o par de (CM_PLAN_ID, Individual_ID) não for exclusivo na tabela de status, você poderá precisar de um SELECT DISTINCT t. *.
fonte
1.Usando com
EXISTS
[Tempo médio de consulta: 1,42s]2.Usando com duas linhas
IN
Cláusula [Tempo médio de consulta: 0,37s]3.Usando com
INNNER JOIN
padrão [Tempo Médio de Consulta: 2.9s]Então, eu escolhi a segunda opção.
fonte
AND
declarações em vez deOR
declarações.OR
declaração provavelmente gera duplicações. No meu caso, não há nenhuma linha que contenha o mesmosrc_id
edest_id
em uma única linha. Portanto, duplicações não acontecerão no meu caso.Inquerir:
consulta acima funcionou para mim no mysql. consulte o link a seguir ->
https://www.w3resource.com/sql/subqueries/multiplee-row-column-subqueries.php
fonte
Se você deseja uma tabela, use a seguinte consulta
e tabela de dados como segue
Em seguida, faça a saída da seguinte forma
fonte
id in (1,2) and studentName in ('a','b')
totalmente não é o mesmo que(id, studentName) in ((1,'a'),(2,'b'))
. Pense em um registro com id = 2 e nome = 'a'. Obviamente, se o ID for único, o efeito será diminuído, mas, se o ID for único, não precisaremos filtrar os nomes.Nós podemos simplesmente fazer isso.
fonte
Concatenar as colunas juntas de alguma forma é um "hack", mas quando o produto não suporta semi-junções para mais de uma coluna, às vezes você não tem escolha.
Exemplo de onde a solução de junção interna / externa não funcionaria:
Quando as consultas não são triviais por natureza, às vezes você não tem acesso à tabela base definida para realizar junções internas / externas regulares.
Se você usar esse "hack", quando combinar os campos, adicione um delimitador suficiente entre eles para evitar interpretações erradas, por exemplo,
ColA + ":-:" + ColB
fonte
Eu fundei mais fácil assim
Espero que esta ajuda :)
fonte
CM_PLAN_ID = 45
eIndividual_ID = 3
, em seguida, concatenação resulta em453
- que se confunde com o caso em queCM_PLAN_ID = 4
eIndividual_ID = 53
... pedindo problema Eu teria pensado45_3
ou45:3
ainda não é uma solução agradável e, é claro, como @mrdenny diz que os índices não serão utilizados agora que uma transformação ocorreu nas colunas.A maneira simples e errada seria combinar duas colunas usando + ou concatenar e criar uma coluna.
Isso seria muito lento. Não pode ser usado na programação, mas se você estiver apenas consultando para verificar se algo pode ser usado.
fonte