Como faço para facilitar a escrita de consultas complexas em SQL? [fechadas]


42

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.

As visualizações temporárias são realmente bastante úteis, pois você pode fazer coisas em uma tabela (como índices complexos explícitos) que são muito difíceis de sugerir para o analisador SQL.

Pessoalmente, acho mais fácil trapacear usando uma GUI (como o LibreOffice Base "Criar consulta no modo de exibição de design" ou o Office Access "Criar"> "Design de consulta") e depois exibir o SQL que ele produz. Às vezes, é necessário modificar o SQL dada por um designer GUI, mas dá um bom ponto de partida
kurdtpage

Respostas:


49

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.


1
Coisas realmente excelentes. Quero enfatizar novamente os pontos de Jeff ao procurar por junções ESQUERDA e dividir consultas complexas em consultas menores e mais gerenciáveis ​​e depois combiná-las. Escrevo grandes consultas em grandes bancos de dados praticamente todos os dias e essas duas coisas em particular surgem o tempo todo. Sempre execute suas consultas e subconsultas o mais rápido possível, para garantir que você esteja obtendo os dados que espera ver a cada etapa.
CodexArcanum

@CodexArcanum - e quando você executa consultas sobre big data, não faz mal ao uso TOP;)
Jeffo

Concordo em cada declaração de sua sugestão
Alessandro Rossi

28
  1. 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].

  2. 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.

  3. 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_SHIPMENTSe HRhbYd_UU, alguém está fazendo algo muito errado.

  4. 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 de TableName, fique com ela. Se você for para uma nova linha após a select, não faça isso em apenas metade das suas consultas, mas em todas elas.

  5. Não use* , a menos que haja fortes motivos para fazê-lo (como if 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.

  6. 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.


9

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:

    SELECT A.Col1, A.Col2, B.Col1,B.Col2
      FROM (SELECT RealTableZ.Col1, RealTableY.Col2, RealTableY.ID as ID
              FROM RealTableZ 
   LEFT OUTER JOIN RealTableY
                ON RealTableZ.ForeignKeyY=RealTableY.ID
             WHERE RealTableY.Col11>14
            ) As B
        INNER JOIN A
                ON A.ForeignKeyY=B.ID

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ê.


3
Sou bastante especialista em SQL e odeio esse recuo: pode parecer bom, mas completamente inútil "na minha opinião". Dois motivos: não consigo entender claramente se essa junção externa esquerda faz parte da consulta principal ou de uma subconsulta, precisa de um embelezador de código e, sempre que você quiser adicionar algumas linhas, precisará refazer o embelezamento de todo o texto . O recuo do plano que precisa apenas de TABS é muito mais flexível. Não votei sua resposta de forma negativa, mas realmente desencorajo qualquer pessoa que use esse estilo ... especialmente quando eles precisam da minha ajuda.
Alessandro Rossi

7

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.


1
Se você usar um cte, esteja ciente de que a consulta persiste apenas até a próxima consulta ser executada; portanto, em alguns casos em que você estiver usando o cte em várias consultas, pode ser melhor para o desempenho usar uma tabela temporária.
Rachel

3
  1. Familiarize-se com a teoria dos conjuntos, se ainda não o é. O SQL é baseado na teoria de conjuntos, e entender mais sobre conjuntos ajudará você a se familiarizar com o funcionamento do SQL.
  2. Pratique mais SQl, se você estiver aprendendo SQL, levará tempo para entender como fazer tudo; algumas coisas levarão tempo para você realmente entendê-las.
  3. Verifique se as tabelas que você está consultando foram projetadas corretamente
  4. Não tenha medo de usar modos de exibição em consultas selecionadas, especialmente se você tiver um conjunto comum que precise ser refinado de várias maneiras diferentes

1

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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.