Estou achando muito difícil escrever consultas SQL complexas envolvendo junções em várias tabelas (pelo menos 3-4) e envolvendo várias condições aninhadas. As consultas que me pedem para escrever são facilmente descritas por algumas frases, mas podem exigir uma quantidade enganosa de código para serem concluídas. Estou me acostumando a usar exibições temporárias para escrever essas consultas, que parecem meio que uma muleta. Que dicas você pode fornecer para que eu possa facilitar essas consultas complexas? Mais especificamente, como faço para dividir essas consultas nas etapas que eu preciso usar para realmente escrever o código SQL?
Observe que eu sou o SQL que estou sendo solicitado a escrever faz parte das tarefas de casa para um curso de banco de dados, portanto, não quero software que faça o trabalho por mim. Eu quero realmente entender o código que estou escrevendo.
Mais detalhes técnicos:
- O banco de dados está hospedado em um servidor PostgreSQL em execução na máquina local.
- O banco de dados é muito pequeno: não há mais de sete tabelas e a maior tabela possui menos de 50 linhas.
- As consultas SQL estão sendo passadas inalteradas para o servidor, via LibreOffice Base.
Respostas:
Estou baseando a maior parte disso apenas na tentativa de obter a resposta "correta", para que você descubra que existem alguns problemas de desempenho. Não faz sentido acelerar uma consulta incorreta.
Entenda os relacionamentos da tabela - a maioria será um para muitos. Conheça a tabela "muitos". Identifique os campos necessários para suas junções.
Pense nos cenários de junção ESQUERDA - selecione todos os funcionários e seus salários do mês passado. E se eles não recebessem um salário no mês passado?
Conheça o conjunto de resultados: 1) Em uma planilha, insira manualmente pelo menos um registro correto para sua consulta. 2) Escreva a consulta em um formulário simples o suficiente para identificar quantos registros devem ser retornados. Use os dois para testar sua consulta e garantir que ingressar em uma nova tabela não altere o resultado.
Divida sua consulta em partes gerenciáveis - Você não precisa escrever tudo de uma vez. Às vezes, consultas complexas podem ser apenas uma coleção de consultas simples.
Cuidado com os níveis mistos de agregação : se você precisar colocar valores mensais, trimestrais e acumulados no mesmo conjunto de resultados, precisará calculá-los separadamente em consultas agrupadas em valores diferentes.
Saber quando UNION Às vezes, é mais fácil dividir subgrupos em suas próprias instruções de seleção. Se você possui uma tabela combinada com gerentes e outros funcionários e, em cada coluna, é necessário executar instruções Case com base na associação a um desses grupos, pode ser mais fácil gravar uma consulta e união do gerente em uma consulta do funcionário. Cada um conteria sua própria lógica. Ter que incluir itens de tabelas diferentes em linhas diferentes é um uso óbvio.
Fórmulas complexas / aninhadas - tente recuar consistentemente e não tenha medo de usar várias linhas. "CASO QUANDO CASO QUANDO CASO QUANDO" o deixará louco. Aproveite o tempo para pensar sobre isso. Salve os cálculos complexos para o final. Obtenha os registros corretos selecionados primeiro. Em seguida, você ataca fórmulas complexas sabendo que está trabalhando com os valores certos. Ver os valores usados nas fórmulas ajudará a identificar áreas nas quais você deve contabilizar valores NULL e onde lidar com a divisão por erro zero.
Teste frequentemente ao adicionar novas tabelas para garantir que você ainda esteja obtendo o conjunto de resultados desejado e sabendo qual associação ou cláusula é a culpada.
fonte
Recuo seria a primeira coisa a fazer, se você ainda não estiver fazendo. Não só é útil com consultas simples, mas é crucial quando se trata de junções e consultas um pouco mais complexas que a
select top 1 [ColumnName] from [TableName]
.Uma vez recuado corretamente, nada proíbe adicionar comentários dentro da própria consulta, quando apropriado. Não os use demais: se o código for suficientemente explícito, adicionar comentários prejudicará a clareza do código. Mas eles ainda são bem-vindos para as partes menos explícitas da consulta.
Observe que consultas mais longas (incluindo consultas com comentários) significariam maior uso de largura de banda entre o servidor de aplicativos e o servidor de banco de dados. Observe também que, a menos que você esteja trabalhando em um produto em escala do Google com uma enorme quantidade de solicitações por segundo, exigindo desempenho e uso de recursos excepcionais, o tamanho adicionado pelos comentários pode não mudar nada para você em termos de desempenho.
A imposição do mesmo estilo sobre tabelas, colunas etc. também ajuda muito na legibilidade. Quando um banco de dados legado tem as tabelas
PRODUCT
,users
,USERS_ObsoleteDONT_USE
,PR_SHIPMENTS
eHRhbYd_UU
, alguém está fazendo algo muito errado.Também é importante aplicar o mesmo estilo em consultas . Por exemplo, se você estiver escrevendo consultas para o Microsoft SQL Server e decidiu usar em
[TableName]
vez deTableName
, fique com ela. Se você for para uma nova linha após aselect
, não faça isso em apenas metade das suas consultas, mas em todas elas.Não use
*
, a menos que haja fortes motivos para fazê-lo (comoif exists(select * from [TableName] where ...)
no Microsoft SQL Server). Não só*
afeta o desempenho em alguns bancos de dados (se não na maioria), mas também não é útil para o desenvolvedor que usa sua consulta. Da mesma forma, um desenvolvedor deve acessar os valores por nome, nunca por índice.Finalmente, para selects, não há nada errado em fornecer uma visualização . Para qualquer outra coisa, os procedimentos armazenados também podem ser usados, dependendo do projeto e das pessoas com quem você está trabalhando.
People Algumas pessoas odeiam procedimentos armazenados. Outros não gostam deles por vários motivos (perfeitamente válidos, pelo menos para eles).
² Seus colegas, os outros alunos, seu professor etc.
fonte
Um pouco no escuro aqui, mas se você estiver escrevendo muitas visualizações temporárias, talvez ainda não tenha percebido que na maioria dos lugares você pode colocar uma tabela em uma instrução SQL, essa tabela pode ser substituída por uma consulta.
Portanto, em vez de associar a tabela A à exibição temporária B, você pode associar a tabela A à consulta que estava usando como exibição temporária B. Por exemplo:
Este exemplo é inútil, mas deve explicar a sintaxe.
Para visualizações que não são "especiais" (indexadas, particionadas), isso deve resultar no mesmo plano de consulta como se você usasse uma visualização.
Para facilitar a gravação, você pode verificar cada peça para garantir que está obtendo o que espera antes de escrever a consulta inteira.
Peço desculpas se isso já é velho para você.
fonte
Em vez de visualizações temporárias, use a cláusula WITH . Isso facilita muito a decomposição de consultas grandes em partes menores mais legíveis.
fonte
fonte
Como qualquer outra coisa, você deseja dividir o problema em partes gerenciáveis.
É realmente assim que você resolve problemas complexos, a propósito.
Portanto: você deseja verificar a subconsulta para ver se ela realmente retorna o que deseja antes de executar uma consulta externa nela. Você deseja tentar uma junção mínima de cada tabela na qual está participando, para poder ver que realmente está pensando bem. Coisas assim. Esperar digitar tudo e sair exatamente o que você quer em um golpe é simplesmente irreal.
Uma instrução SQL, uma vez que atinge um certo nível de complexidade, é basicamente um pequeno programa em si. Faz uma grande diferença realmente entender como os dados são combinados, selecionados, filtrados e gerados.
fonte