Estou comparando um monte de tabelas de diferentes bancos de dados em diferentes servidores para um registro mestre. Preciso saber quais servidores, identificados por locationID
, possuem as linhas não correspondentes porque podem precisar de manutenção.
Eu tenho uma EXCEPT
consulta simples onde comparo uma tabela onde cada linha é a configuração de cada servidor; table1
tem uma linha por servidor com todas as configurações mais locationID
que é uma coluna que me diz qual servidor é. Eu comparo tudo isso com uma table1_master
tabela que tem as configurações corretas, mas excluo o locationID
porque não corresponderá.
Consulta simples abaixo:
SELECT everything, but, locationID
FROM table1
EXCEPT
SELECT everything, but, locationID
FROM table1_master
Há apenas uma linha mestre com a qual comparo todos os servidores e não a seleciono locationID
aqui.
Este é um exemplo das linhas que estou comparando. Cada um tem uma chave primária, uma única coluna varchar
e uma lista gigante com dezenas de colunas. Desejo comparar todas as colunas , exceto LocationID, mas preciso de LocationID para identificar as linhas.
LocationID setting setting setting setting
CS02 C Y Y Y Y
CS03 C Y Y Y Y
CS06 C Y N Y Y
Neste exemplo, digamos que CS02 é meu registro mestre, então, como todas as configurações são as mesmas em CS02 e CS03, essas linhas não aparecem, mas CS06 sim. Mas em minha EXCEPT
consulta, não estou capturando LocationID, então não sei qual linha foi retornada.
Isso retorna as linhas de que preciso, mas NÃO o locationID
, então não sei quais linhas estão erradas. Existe alguma maneira de incluir locationID
no conjunto de resultados enquanto excluo as linhas correspondentes?
A solução que pensei foi fazer uma linha para cada servidor da table1_master
tabela, assim cada um locationID
fica representado, mas todos tem os mesmos dados fora isso. Minha EXCLUDE
consulta deve retornar locationID
e minhas informações, mas essa é a melhor maneira de fazer isso?
Você também pode fazer isso com SQL dinâmico sem precisar criar manualmente todos os nomes de coluna.
Você pode pegar a saída desta consulta como está e armazená-la em algum lugar, ou pode comentar
SELECT
e descomentarEXEC
e deixá-la como SQL dinâmico permanente - neste caso, ela se adaptará automaticamente às alterações de coluna nas duas tabelas.Outra ideia (assumindo que LocationID é único) - e me ocorreu que você pode querer incluir a linha mestre para que possa identificar rapidamente as colunas que são diferentes:
Esta versão é um pouco mais barata (principalmente evitando a
DISTINCT
comparação com a tabela mestre, ao custo de precisar especificar todas as colunas mais uma vez - o que novamente você pode automatizar conforme acima):No entanto, todas essas opções são de desempenho inferior com planos piores do que o simples de Rachel
LEFT JOIN
. Tentei me ater ao tema do usoEXCEPT
, embora seja mais uma questão de sintaxe do que de desempenho.A principal conclusão é que, se a contagem de colunas for muito alta para lidar manualmente, você pode usar a abordagem SQL dinâmica acima para construir qualquer consulta que deseja usar - e você pode fazer isso uma vez e armazenar o resultado ou ter o código gerado todas as vezes. Para gerar a consulta de Rachel usando SQL dinâmico, não precisa mudar muito:
Eu recomendaria:
Hash
campo que é uma coluna computada persistente com uma definição ao longo das linhas deHASHBYTES('SHA1', Field1 + Field2 + Field3...)
HASH
valor do seu "mestre" com seus outros registrosAlgo como
O que há de errado em apenas unir as duas tabelas em cada coluna (ou usar uma instrução where) e selecionar itens que não existem na segunda tabela?
Pode não ser bonito, mas deve funcionar