¿Cómo hago que las consultas complejas de SQL sean más fáciles de escribir? [cerrado]

42

Me resulta muy difícil escribir consultas SQL complejas que involucren uniones en muchas tablas (al menos 3-4) e involucren varias condiciones anidadas. Las consultas que se me pide que escriba se describen fácilmente con unas pocas oraciones, pero pueden requerir una cantidad engañosa de código para completar. Me encuentro a menudo usando vistas temporales para escribir estas consultas, que parecen un poco muletas. ¿Qué consejos me puede proporcionar que pueda utilizar para facilitar estas consultas complejas? Más específicamente, ¿cómo divido estas consultas en los pasos que necesito usar para escribir realmente el código SQL?

Tenga en cuenta que soy el SQL que se me pide que escriba es parte de las tareas para un curso de base de datos, por lo que no quiero un software que haga el trabajo por mí. Quiero entender realmente el código que estoy escribiendo.

Más detalles técnicos:

  • La base de datos está alojada en un servidor PostgreSQL que se ejecuta en la máquina local.
  • La base de datos es muy pequeña: no hay más de siete tablas y la tabla más grande tiene menos de aproximadamente 50 filas.
  • Las consultas SQL se pasan sin modificaciones al servidor, a través de LibreOffice Base.
bwDraco
fuente
Las vistas temporales son realmente bastante útiles, ya que puede hacer cosas en una tabla de este tipo (como índices complejos explícitos) que es muy difícil de insinuar en el analizador SQL.
Personalmente, me resulta más fácil hacer trampa usando una GUI (como LibreOffice Base "Crear consulta en la vista de diseño" u Office Access "Crear"> "Diseño de consulta") y luego ver el SQL que esto produce. A veces es necesario modificar el SQL proporcionado por un diseñador de GUI, pero proporciona un buen punto de partida
kurdtpage

Respuestas:

49

Estoy basando la mayor parte de esto en tratar de obtener la respuesta "correcta", por lo que puede descubrir que hay algunos problemas de rendimiento. No tiene sentido acelerar una consulta incorrecta.

Comprenda las relaciones de la tabla : la mayoría será de una a muchas. Conozca la tabla "muchos". Identifique los campos requeridos para sus uniones.

Piense en los escenarios de unión IZQUIERDA : seleccione todos los empleados y su cheque de pago del mes pasado. ¿Qué pasa si no recibieron un cheque de pago el mes pasado?

Conozca el conjunto de resultados: 1) En una hoja de cálculo, ingrese manualmente al menos un registro correcto para su consulta. 2) Escriba la consulta de forma suficientemente simple para identificar cuántos registros deben devolverse. Use ambos para probar su consulta y asegurarse de que unirse a una nueva tabla no altere el resultado.

Divida su consulta en partes manejables : no tiene que escribirla de una vez. Las consultas complejas a veces pueden ser solo una colección de consultas simples.

Tenga cuidado con los niveles mixtos de agregación : si tiene que poner valores mensuales, trimestrales y anuales hasta la fecha en el mismo conjunto de resultados, deberá calcularlos por separado en consultas agrupadas en diferentes valores.

Sepa cuándo UNIR A veces es más fácil dividir los subgrupos en sus propias declaraciones de selección. Si tiene una tabla mezclada con gerentes y otros empleados, y en cada columna debe hacer declaraciones de casos basadas en la membresía en uno de estos grupos, puede ser más fácil escribir una consulta de Gerente y unir a una consulta de Empleado. Cada uno contendría su propia lógica. Tener que incluir elementos de diferentes tablas en diferentes filas es un uso obvio.

Fórmulas complejas / anidadas : intente sangrar constantemente y no tenga miedo de usar varias líneas. "CASO CUANDO CASO CUANDO CASO CUANDO" te volverá loco. Tómese el tiempo para pensar en esto. Guarde los cálculos complejos para el final. Obtenga los registros correctos seleccionados primero. Luego atacas fórmulas complejas sabiendo que estás trabajando con los valores correctos. Ver los valores utilizados en las fórmulas lo ayudará a detectar áreas donde debe tener en cuenta los valores NULL y dónde manejar el error de división por cero.

Pruebe a menudo a medida que agrega nuevas tablas para asegurarse de que todavía obtiene el conjunto de resultados deseado y sabe qué unión o cláusula es la culpable.

JeffO
fuente
1
Cosas realmente excelentes. Quiero volver a enfatizar los puntos de Jeff al buscar uniones IZQUIERDA y dividir consultas complejas en preguntas más pequeñas y manejables y luego combinarlas. Escribo grandes consultas en grandes bases de datos casi todos los días y esas dos cosas en particular surgen todo el tiempo. Siempre ejecute sus consultas y subconsultas tan pronto como sea posible, para asegurarse de obtener los datos que espera ver en cada paso.
CodexArcanum
@CodexArcanum - y cuando ejecuta consultas en big data, no está de más usar TOP;)
JeffO
Estoy de acuerdo con cada declaración de su sugerencia
Alessandro Rossi
28
  1. La sangría sería lo primero que debería hacer, si aún no lo está haciendo. No solo es útil incluso con consultas simples, sino que es crucial cuando se trata de uniones y consultas un poco más complejas que a select top 1 [ColumnName] from [TableName].

  2. Una vez sangrado correctamente, nada prohíbe agregar comentarios dentro de la consulta, cuando sea apropiado. No los use en exceso: si el código es lo suficientemente explícito, agregar comentarios solo dañará la claridad del código. Pero todavía son bienvenidos para las partes menos explícitas de la consulta.

    Tenga en cuenta que las consultas más largas (incluidas las consultas con comentarios) significarían un mayor uso de ancho de banda entre su servidor de aplicaciones y su servidor de base de datos. También tenga en cuenta que a menos que esté trabajando en un producto a escala de Google con una gran cantidad de solicitudes por segundo, que requiera un rendimiento excepcional y un uso de recursos, el tamaño agregado por los comentarios puede no cambiar nada para usted en términos de rendimiento.

  3. Aplicar el mismo estilo sobre tablas, columnas, etc. también ayuda mucho a la legibilidad. Cuando una base de datos existente tiene las tablas PRODUCT, users, USERS_ObsoleteDONT_USE, PR_SHIPMENTSy HRhbYd_UU, alguien está haciendo algo muy malo.

  4. Aplicar el mismo estilo sobre las consultas también es importante. Por ejemplo, si está escribiendo consultas para Microsoft SQL Server y decidió usarlas en [TableName]lugar de hacerlo TableName, quédese con ellas. Si va a una nueva línea después de un select, no lo haga solo en la mitad de sus consultas, sino en todas.

  5. No lo use* , a menos que haya razones sólidas para hacerlo (como if exists(select * from [TableName] where ...)en Microsoft SQL Server). No solo *tiene un impacto negativo en el rendimiento en algunas (si no la mayoría) de las bases de datos, sino que tampoco es útil para el desarrollador que utiliza su consulta. Del mismo modo, un desarrollador debe acceder a los valores por nombre, nunca por índice.

  6. Finalmente, para las selecciones, no hay nada de malo en proporcionar una vista . Para cualquier otra cosa, los procedimientos almacenados también pueden usarse según el proyecto y las personas con las que está trabajando².


¹ Algunas personas odian los procedimientos almacenados. A otros no les gustan por varias razones (perfectamente válidas, al menos por ellas).

² Tus colegas, los otros estudiantes, tu profesor, etc.

Arseni Mourzenko
fuente
9

Aquí hay un poco de oscuridad, pero si está escribiendo muchas vistas temporales, quizás aún no se haya dado cuenta de que en la mayoría de los lugares donde podría colocar una tabla en una declaración SQL, esa tabla puede reemplazarse por una consulta.

Entonces, en lugar de unir la tabla A a la vista temporal B, puede unir la tabla A a la consulta que ha estado utilizando como vista temporal B. Por ejemplo:

    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 ejemplo no tiene sentido, pero debería explicar la sintaxis.

Para las vistas que no son "especiales" (indexadas, particionadas), esto debería dar como resultado el mismo plan de consulta que si utilizara una vista.

En cuanto a facilitar la escritura, puede verificar cada pieza para asegurarse de obtener lo que espera antes de escribir toda la consulta.

Mis disculpas si esto ya es viejo para ti.

psr
fuente
3
Soy bastante experto en SQL y realmente odio esta sangría: puede verse bien pero es completamente inútil "en mi opinión". Dos razones: no puedo entender claramente si esa combinación externa izquierda es parte de la consulta principal o parte de una subconsulta, necesita un embellecedor de código y cada vez que desea agregar algunas líneas necesita volver a embellecer todo el texto . La sangría del plan que solo necesita TABS es mucho más flexible. No rechacé su respuesta, pero realmente desaliento a cualquiera que use este estilo ... especialmente cuando necesitan mi ayuda.
Alessandro Rossi
7

En lugar de vistas temporales, use la cláusula WITH . Esto hace que sea mucho más fácil dividir las consultas grandes en partes más pequeñas más legibles.

usuario281377
fuente
1
Si usa un cte, tenga en cuenta que la consulta solo persiste hasta que se ejecute la siguiente consulta, por lo que en algunos casos donde está usando el cte en múltiples consultas, podría ser mejor para el rendimiento usar una tabla temporal.
Rachel
3
  1. Familiarícese con la teoría de conjuntos si aún no lo ha hecho. SQL se basa en la teoría de conjuntos y comprender más sobre los conjuntos lo ayudará a familiarizarse con el funcionamiento de SQL.
  2. Practique más SQl, si solo está aprendiendo SQL, tomará tiempo entender cómo hacerlo todo, algunas cosas solo toman tiempo antes de que realmente las entienda, las uniones son un gran ejemplo, cuanto más las use, mejor lo conseguirá.
  3. Asegúrese de que las tablas que está consultando estén diseñadas correctamente
  4. No tenga miedo de usar vistas en consultas seleccionadas, especialmente si tiene un conjunto común que necesita ser refinado de varias maneras diferentes
Ryathal
fuente
1

Como cualquier otra cosa, desea dividir el problema en partes manejables.

Por cierto, así es como resuelves problemas complejos.

Entonces: desea consultar la subconsulta para ver que realmente devuelve lo que desea antes de ejecutar una consulta externa. Desea probar una combinación mínima de cada tabla en la que se está uniendo para poder ver que realmente está pensando bien. Ese tipo de cosas. Esperar escribirlo todo y sacar exactamente lo que quieres de un golpe no es realista.

Una declaración SQL, una vez que alcanza un cierto nivel de complejidad, es básicamente un pequeño programa en sí mismo. Hace una gran diferencia comprender realmente cómo se combinan, seleccionan, filtran y generan los datos.

Dan Ray
fuente