indentar - Formato de consultas SQL claras y legibles
indentar codigo sql server (11)
Estoy escribiendo algunas consultas SQL con varias subconsultas y muchas uniones en todas partes, tanto dentro de la subconsulta como en la tabla resultante de la subconsulta.
No estamos usando vistas, así que eso está fuera de discusión.
Después de escribirlo, lo estoy mirando y rascándome la cabeza preguntándome qué está haciendo porque no puedo seguirlo.
¿Qué tipo de formato utilizas para intentar limpiar ese desorden? ¿Tal vez sangrías?
Chico es esta una pregunta cargada. :) Hay tantas formas de hacerlo correctamente como personas inteligentes en este sitio. Dicho esto, aquí es cómo me mantengo sano cuando construyo sentencias complejas de SQL:
select
c.customer_id
,c.customer_name
,o.order_id
,o.order_date
,o.amount_taxable
,od.order_detail_id
,p.product_name
,pt.product_type_name
from
customer c
inner join
order o
on c.customer_id = o.customer_id
inner join
order_detail od
on o.order_id = od.order_id
inner join
product p
on od.product_id = p.product_id
inner join
product_type pt
on p.product_type_id = pt.product_type_id
where
o.order_date between ''1/1/2011'' and ''1/5/2011''
and
(
pt.product_type_name = ''toys''
or
pt.product_type_name like ''%kids%''
)
order by
o.order_date
,pt.product_type_name
,p.product_name
Si está interesado, puedo publicar / enviar diseños para inserciones, actualizaciones y eliminaciones, así como subconsultas correlacionadas y complejos predicados de unión.
¿Responde esto a tu pregunta?
En general, sigo un conjunto jerárquico simple de reglas de formato. Básicamente, palabras clave como SELECT, FROM, ORDER BY van en su propia línea. Cada campo va en su propia línea (de manera recursiva)
SELECT
F.FIELD1,
F.FIELD2,
F.FIELD3
FROM
FOO F
WHERE
F.FIELD4 IN
(
SELECT
B.BAR
FROM
BAR B
WHERE
B.TYPE = 4
AND B.OTHER = 7
)
Generalmente, la gente rompe líneas en palabras reservadas y sangra cualquier subconsulta:
SELECT *
FROM tablename
WHERE value in
(SELECT *
FROM tablename2
WHERE condition)
ORDER BY column
Indenting ciertamente, pero también puede dividir las subconsultas con comentarios, hacer que los nombres de sus alias sean realmente significativos y especificar a qué subconsulta se refieren, por ejemplo, innerCustomer, outerCustomer.
Common Table Expressions realmente puede ayudar en algunos casos a dividir una consulta en secciones significativas.
La única forma verdadera y correcta de formatear SQL es:
SELECT t.mycolumn AS column1
,t.othercolumn AS column2
,SUM(t.tweedledum) AS column3
FROM table1 t
,(SELECT u.anothercol
,u.memaw /*this is a comment*/
FROM table2 u
,anothertable x
WHERE u.bla = :b1 /*the bla value*/
AND x.uniquecol = :b2 /*the widget id*/
) v
WHERE t.tweedledee = v.anothercol
AND t.hohum = v.memaw
GROUP BY t.mycolumn
,t.othercolumn
HAVING COUNT(*) > 1
;
;)
Sin embargo, en serio, me gusta usar cláusulas WITH (como ya se sugirió) para domesticar consultas SQL muy complicadas.
Los alias de la tabla y la consistencia simple lo llevarán a un largo, largo camino
Lo que parece decente es romper líneas en las palabras clave SELECT, FROM, WHERE (etc.).
Las uniones pueden ser más complicadas, sangrar la parte ON de las uniones resalta la parte importante de la misma al frente.
Romper expresiones lógicas complicadas (unir y donde ambas condiciones) en el mismo nivel también ayuda.
Sangrando lógicamente el mismo nivel de declaración (subconsultas, paréntesis de apertura, etc.)
Poner en mayúscula todas las palabras clave y funciones estándar.
El SQL realmente complejo no se alejará de los comentarios, aunque normalmente los encontrará en scripts SQL y no en SQL dinámico.
Ejemplo de edición:
SELECT a.name, SUM(b.tax)
FROM db_prefix_registered_users a
INNER JOIN db_prefix_transactions b
ON a.id = b.user_id
LEFT JOIN db_countries
ON b.paid_from_country_id = c.id
WHERE a.type IN (1, 2, 7) AND
b.date < (SELECT MAX(date)
FROM audit) AND
c.country = ''CH''
Entonces, al final para resumirlo, la consistencia es lo más importante.
Me gusta usar algo como:
SELECT col1,
col2,
...
FROM
MyTable as T1
INNER JOIN
MyOtherTable as T2
ON t1.col1 = t2.col1
AND t1.col2 = t2.col2
LEFT JOIN
(
SELECT 1,2,3
FROM Someothertable
WHERE somestuff = someotherstuff
) as T3
ON t1.field = t3.field
Póngalo en una vista para que sea más fácil de visualizar, tal vez mantenga una captura de pantalla como parte de la documentación. No tiene que guardar la vista ni usarla para ningún otro propósito.
Una pregunta histórica con mil opiniones y ninguna respuesta correcta, y una de mis favoritas. Aquí están mis dos centavos.
En lo que respecta a las subconsultas, últimamente me ha resultado más fácil seguir lo que está pasando con sangría "extrema" y agregar comentarios de esta manera:
SELECT mt.Col1, mt.Col2, subQ.Dollars
from MyTable1 mt
inner join (-- Get the dollar total for each SubCol
select SubCol, sum(Dollars) Dollars
from MyTable2
group by SubCol) subQ
on subQ.SubCol = mt.Col1
order by mt.Col2
En cuanto al otro centavo, solo uso mayúsculas en la primera palabra. Con las páginas de consultas de ejecución, hace que sea un poco más fácil elegir cuándo comienza una nueva.
Su kilometraje, por supuesto, variará.
Wow, muchas respuestas aquí, pero una cosa que no he visto en muchas son COMENTARIOS! Tiendo a agregar muchos comentarios a lo largo, especialmente con grandes sentencias de SQL. El formato es importante, pero los comentarios bien colocados y significativos son extremadamente importantes, no solo para usted, sino también para la pobre alma que necesita mantener el código;)
Con consultas grandes, tiendo a confiar mucho en conjuntos de resultados con nombre usando WITH
. Esto permite definir el conjunto de resultados de antemano y simplifica la consulta principal. Los conjuntos de resultados con nombre pueden ayudar a hacer que el plan de consulta sea más eficiente, por ejemplo, postgres almacena el conjunto de resultados en una tabla temporal.
Ejemplo:
WITH
cubed_data AS (
SELECT
dimension1_id,
dimension2_id,
dimension3_id,
measure_id,
SUM(value) value
FROM
source_data
GROUP BY
CUBE(dimension1, dimension2, dimension3),
measure
),
dimension1_label AS(
SELECT
dimension1_id,
dimension1_label
FROM
labels
WHERE
object = ''dimension1''
), ...
SELECT
*
FROM
cubed_data
JOIN dimension1_label USING (dimension1_id)
JOIN dimension2_label USING (dimension2_id)
JOIN dimension3_label USING (dimension3_id)
JOIN measure_label USING (measure_id)
El ejemplo es un poco artificial, pero espero que muestre un aumento en la claridad en comparación con las subconsultas en línea. Los conjuntos de resultados con nombre me han sido de gran ayuda cuando he estado preparando datos para el uso de OLAP. Los conjuntos de resultados con nombre también son obligatorios si tiene / desea crear consultas recursivas.
WITH
funciona al menos en las versiones actuales de Postgres, Oracle y SQL Server