query - separador de miles sql
Estándares de formato SQL (26)
En mi último trabajo trabajamos en una gran aplicación de base de datos y desarrollé algunos estándares de formato para que todos escribiéramos SQL con un diseño común. También desarrollamos estándares de codificación, pero estos son más específicos de la plataforma, así que no entraré en ellos aquí.
Me interesa saber qué usan otras personas para los estándares de formato SQL. A diferencia de la mayoría de los entornos de codificación, ya que no he encontrado mucho consenso en línea para ellos.
Para cubrir los principales tipos de consulta:
select
ST.ColumnName1,
JT.ColumnName2,
SJT.ColumnName3
from
SourceTable ST
inner join JoinTable JT
on JT.SourceTableID = ST.SourceTableID
inner join SecondJoinTable SJT
on ST.SourceTableID = SJT.SourceTableID
and JT.Column3 = SJT.Column4
where
ST.SourceTableID = X
and JT.ColumnName3 = Y
Hubo algún desacuerdo sobre las alimentaciones de línea después de "seleccionar", "de" y "dónde". La intención en la línea de selección es permitir que otros operadores como "X superior" sin alterar el diseño. Después de eso, simplemente mantener un flujo de línea consistente después de los elementos de consulta clave, pareció dar como resultado un buen nivel de legibilidad.
Dejar caer el salto de línea después de "desde" y "dónde" sería una revisión comprensible. Sin embargo, en consultas como la "actualización" a continuación, vemos que el avance de línea después del "dónde" nos da una buena alineación de columnas. Del mismo modo, un salto de línea después de "agrupar por" o "ordenar por" mantiene nuestros diseños de columna claros y fáciles de leer.
update
TargetTable
set
ColumnName1 = @value,
ColumnName2 = @value2
where
Condition1 = @test
Finalmente un inserto:
insert into TargetTable (
ColumnName1,
ColumnName2,
ColumnName3
) values (
@value1,
@value2,
@value3
)
En su mayor parte, estos no se desvían tanto de la forma en que MS SQL Server Management Studio / query analyzer escribe SQL, sin embargo , difieren.
Estoy ansioso por ver si hay algún consenso en la comunidad de Stack Overflow sobre este tema. Estoy constantemente sorprendido de cuántos desarrolladores pueden seguir el formato estándar para otros idiomas y de repente van tan al azar cuando tocan SQL.
Bonito. Como programador de Python, estas son mis preferencias:
Líneas nuevas después de "seleccionar", "de" y "dónde" solo cuando es necesario para la legibilidad.
Cuando el código de código puede ser más compacto e igualmente legible, generalmente prefiero la forma más compacta. Ser capaz de incluir más código en una pantalla mejora la productividad.
select ST.ColumnName1, JT.ColumnName2, SJT.ColumnName3
from SourceTable ST
inner join JoinTable JT
on JT.SourceTableID = ST.SourceTableID
inner join SecondJoinTable SJT
on ST.SourceTableID = SJT.SourceTableID
and JT.Column3 = SJT.Column4
where ST.SourceTableID = X and JT.ColumnName3 = Y
En última instancia, esta será una llamada de juicio que se realizará durante la revisión del código.
Para insert
, colocaría los parens de manera diferente:
insert into TargetTable (
ColumnName1,
ColumnName2,
ColumnName3)
values (
@value1,
@value2,
@value3)
El razonamiento para este formato es que si SQL usó idendation para estructura de bloque (como Python), entonces el paréntesis no sería necesario. Entonces, si la sangría se usa de todos modos, los paréntesis deberían tener el efecto mínimo en el diseño. Esto se logra colocándolos al final de las líneas.
Creo que tener unas buenas reglas de formato es realmente importante porque puedes detectar y corregir errores fácilmente. Como se dice: "Está escribiendo código una vez, este código se lee y luego 10000000 de veces", por lo que siempre es bueno dedicar algo de tiempo al formateo. Los objetivos principales son:
- Haga que su código sea más fácil de leer y entender
- Minimice el esfuerzo requerido para mantener o extender su código
- Reduzca la necesidad de que los usuarios y desarrolladores de un sistema consulten fuentes secundarias de documentación, como comentarios de códigos o manuales de software
Algunas reglas que siempre uso:
- Siempre usa . notación
- Siempre use alias antes de la columna, entonces. notación
- Pongo yo
and
hasta el final de la línea - No use soportes de unnishccary
- No use MAYÚSCULAS
- Por lo general, prefiere cte a subconsultas anidadas
Como ejemplo, aquí cómo formatearía la consulta utilizada como ejemplo en esta pregunta:
select
ST.ColumnName1,
JT.ColumnName2,
SJT.ColumnName3
from <schema>.SourceTable as ST
inner join <schema>.JoinTable as JT on
ST.SourceTableID = JT.SourceTableID
inner join <schema>.SecondJoinTable as SJT on
SJT.SourceTableID = ST.SourceTableID and
SJT.Column4 = JT.Column3
where
ST.SourceTableID = X and
JT.ColumnName3 = Y
Y consulta de "estudiantes":
select
term,
student_id,
case
when (ft_credits > 0 and credits >= ft_credits) or (ft_hours_per_week > 3 and hours_per_week >= ft_hours_per_week) then ''F''
else ''P''
end as [status]
from (
select
a.term,
a.student_id,
pm.credits as ft_credits,
pm.[hours] as ft_hours_per_week,
sum(a.credits) as credits,
sum(a.hours_per_week) as hours_per_week
from (
select
e.term, e.student_id, NVL(o.credits, 0) credits,
case
when NVL(o.weeks, 0) > 5 then
(NVL(o.lect_hours, 0) + NVL(o.lab_hours, 0) + NVL(o.ext_hours, 0)) / NVL(o.weeks, 0)
else
0
end as hours_per_week
from enrollment as e
inner join offering as o using (term, offering_id)
inner join program_enrollment as pe on pe.student_id = e.student_id and pe.term = e.term and pe.offering_id = e.offering_id
where
e.registration_code Not in (''A7'', ''D0'', ''WL'')
) as a
inner join student_history as sh using (student_id)
inner join program_major as pm on pm._major_code = sh.major_code_1 and pm.division_code = sh.division_code_1
where
sh.eff_term =
(
select max(eff_term)
from student_history as shi
where
shi.student_id = sh.student_id and
shi.eff_term <= term
)
group by
a.term,
a.student_id,
pm.credits,
pm.[hours]
) as a
order by
term,
student_id
El número de opiniones diferentes es aterrador. Esto es lo que mi organización usa:
SELECT ST.ColumnName1,
JT.ColumnName2,
SJT.ColumnName3
FROM SourceTable ST
INNER JOIN JoinTable JT ON JT.SourceTableID = ST.SourceTableID
INNER JOIN SecondJoinTable SJT ON ST.SourceTableID = SJT.SourceTableID
AND JT.Column3 = SJT.Column4
WHERE ST.SourceTableID = X
AND JT.ColumnName3 = Y
Mantener la sangría de 8 caracteres es clave para la legibilidad en mi humilde opinión.
Estoy totalmente de acuerdo con su esfuerzo por estandarizar el formato SQL dentro de su proyecto y en general.
También estoy muy de acuerdo con sus opciones de formato. He encontrado casi el mismo, salvo que también sangré las declaraciones ''join'', y con ellas las declaraciones ''on'' una sangría más.
Muy parecido al hecho de que vayas en minúsculas en las palabras clave. ¿Quién quiere recibir esas GRACIAS? También prefiero reducir los alias de la tabla de casos, lo que permite una mejor legibilidad
Muy parecido al hecho de que usas una pequeña sangría (4). Voy con (3).
Considero que los términos "interno" y "externo" no son necesarios.
Aquí es cómo habría formateado su declaración seleccionada:
select
st.ColumnName1,
jt.ColumnName2,
sjt.ColumnName3
from
SourceTable st
join JoinTable jt on jt.SourceTableID = st.SourceTableID
join SecondJoinTable sjt on
st.SourceTableID = sjt.SourceTableID and
jt.Column3 = sjt.Column4
where
st.SourceTableID = X
and jt.ColumnName3 = Y
;
Gracias por discutir esto.
Estoy trabajando en la escritura de un formateador de SQL de fuente abierta (SQL Server solo en esta etapa) en C #, así que puse las consultas anteriores a través de él.
Emplea una estrategia similar al OP, es decir, que cada ''sección'' tiene elementos secundarios sangrados debajo. Cuando sea necesario, agrego un espacio en blanco entre las secciones para ayudar a la claridad; estas no se agregarán cuando no haya uniones o un mínimo donde las condiciones
Resultado:
SELECT
ST.ColumnName1,
JT.ColumnName2,
SJT.ColumnName3
FROM SourceTable ST
INNER JOIN JoinTable JT
ON JT.SourceTableID = ST.SourceTableID
INNER JOIN SecondJoinTable SJT
ON ST.SourceTableID = SJT.SourceTableID
AND ST.SourceTable2ID = SJT.SourceTable2ID
WHERE ST.SourceTableID = X
AND JT.ColumnName3 = Y
AND JT.Column3 = SJT.Column4
ORDER BY
ST.ColumnName1
Hay muchos puntos buenos en este hilo. El único estándar que he intentado convencer a las personas para que utilicen es colocar la coma en la misma línea antes de cada columna. Al igual que:
Select column1
,column2
,column3
,column4
,Column5 ...ect
Oposición a:
Select column1,
column2,
column3, ect...
La razón por la que prefiero esta práctica es porque, si es necesario, puedes comentar una línea y no habrá un problema de coma cuando lo ejecutes debido a que la coma correspondiente está siendo comentada también. Sé que vi a otro usuario en el hilo que también lo había hecho pero que en realidad no lo señaló. No es una gran revelación para llevar a la conversación, pero mis dos centavos. Gracias
Llego tarde a la fiesta, pero solo agregaré mi estilo de formato preferido, que debo haber aprendido de libros y manuales: es compacto. Aquí está la declaración SELECT
muestra:
SELECT st.column_name_1, jt.column_name_2,
sjt.column_name_3
FROM source_table AS st
INNER JOIN join_table AS jt USING (source_table_id)
INNER JOIN second_join_table AS sjt ON st.source_table_id = sjt.source_table_id
AND jt.column_3 = sjt.column_4
WHERE st.source_table_id = X
AND jt.column_name_3 = Y
En resumen: sangría de 8 espacios, palabras clave en mayúsculas (aunque SO los colorea mejor cuando está en minúsculas), sin camelcase (sin sentido en Oracle) y envolturas de línea cuando sea necesario.
La UPDATE
:
UPDATE target_table
SET column_name_1 = @value,
column_name_2 = @value2
WHERE condition_1 = @test
Y el INSERT
:
INSERT INTO target_table (column_name_1, column_name_2,
column_name_3)
VALUES (@value1, @value2, @value3)
Ahora, déjame ser el primero en admitir que este estilo tiene sus problemas. La sangría de 8 espacios significa que ORDER BY
y GROUP BY
desalinean la sangría o dividen la palabra BY
off por sí misma. También sería más natural aplicar sangría al predicado completo de la cláusula WHERE
, pero generalmente alineo los siguientes operadores AND
y OR
en el margen izquierdo. La sangría después de las líneas envueltas INNER JOIN
también es algo arbitraria.
Pero por alguna razón, todavía me resulta más fácil de leer que las alternativas.
Terminaré con una de mis creaciones más complejas últimamente usando este estilo de formateo. Casi todo lo que encontrarías en una declaración SELECT
aparece en este. (También se ha alterado para ocultar sus orígenes, y es posible que haya introducido errores al hacerlo).
SELECT term, student_id,
CASE
WHEN ((ft_credits > 0 AND credits >= ft_credits) OR (ft_hours_per_week > 3 AND hours_per_week >= ft_hours_per_week)) THEN ''F''
ELSE ''P''
END AS status
FROM (
SELECT term, student_id,
pm.credits AS ft_credits, pm.hours AS ft_hours_per_week,
SUM(credits) AS credits, SUM(hours_per_week) AS hours_per_week
FROM (
SELECT e.term, e.student_id, NVL(o.credits, 0) credits,
CASE
WHEN NVL(o.weeks, 0) > 5 THEN (NVL(o.lect_hours, 0) + NVL(o.lab_hours, 0) + NVL(o.ext_hours, 0)) / NVL(o.weeks, 0)
ELSE 0
END AS hours_per_week
FROM enrollment AS e
INNER JOIN offering AS o USING (term, offering_id)
INNER JOIN program_enrollment AS pe ON e.student_id = pe.student_id AND e.term = pe.term AND e.offering_id = pe.offering_id
WHERE e.registration_code NOT IN (''A7'', ''D0'', ''WL'')
)
INNER JOIN student_history AS sh USING (student_id)
INNER JOIN program_major AS pm ON sh.major_code_1 = pm._major_code AND sh.division_code_1 = pm.division_code
WHERE sh.eff_term = (
SELECT MAX(eff_term)
FROM student_history AS shi
WHERE sh.student_id = shi.student_id
AND shi.eff_term <= term)
GROUP BY term, student_id, pm.credits, pm.hours
)
ORDER BY term, student_id
Esta abominación calcula si un estudiante es a tiempo completo o a tiempo parcial en un término determinado. Independientemente del estilo, este es difícil de leer.
Me doy cuenta de que llegué muy tarde a este debate, pero me gustaría dar mi opinión. Definitivamente estoy a favor de las comas al inicio de la línea. Como dices AdamRalph es más fácil comentar un campo y también me resulta más difícil perder una coma accidentalmente cuando están al principio, aunque esto no suena como un problema importante. He pasado horas tratando de hacerlo en el pasado. para rastrear errores de sintaxis accidentales en largos procedimientos de T-SQL donde accidentalmente he perdido una coma al final de la línea (estoy seguro de que algunos de ustedes probablemente lo hayan hecho también). También estoy a favor de aliasing tanto como sea posible.
En general, me doy cuenta de que todo se reduce a las preferencias personales, lo que funciona para algunos no lo es para los demás. Siempre que pueda leer el código fácilmente y cada desarrollador muestre cierta consistencia en su estilo, creo que eso es lo más importante.
Me gusta que mi SQL esté formateado de esa manera, aunque mientras la intención sea fácil de leer, la mayoría de los formatos funcionarán. Realmente odio ver las declaraciones creadas en el diseñador de consultas y luego me fui de esa manera. Si estoy editando el procedimiento / vista / función / disparador de otra persona, etc., intentaré mantener el formato ya utilizado (a menos que sea realmente malo, lo reformatearé todo).
Seleccionar declaración
SELECT ST.ColumnName1, JT.ColumnName2, SJT.ColumnName3
FROM SourceTable ST INNER JOIN
JoinTable JT ON JT.SourceTableID = ST.SourceTableID
INNER JOIN
SecondJoinTable SJT ON ST.SourceTableID = SJT.SourceTableID
AND JT.Column3 = SJT.Column4
WHERE (ST.SourceTableID = X)
AND (JT.ColumnName3 = Y);
Declaración de actualización
UPDATE TargetTable SET
ColumnName1 = @value,
ColumnName2 = @value2
WHERE (Condition1 = @test);
Insertar declaración
INSERT INTO TargetTable
(
ColumnName1,
ColumnName2,
ColumnName3
)
values
(
@value1,
@value2,
@value3
);
Me gusta:
SELECT ST.ColumnName1, JT.ColumnName2, SJT.ColumnName3 --leave all selected columns on the same line
FROM
SourceTable ST
INNER JOIN JoinTable JT ON JT.SourceTableID = ST.SourceTableID
INNER JOIN SecondJoinTable SJT --only splitting lines when more than 1 condition
ON ST.SourceTableID = SJT.SourceTableID
AND JT.Column3 = SJT.Column4
WHERE
ST.SourceTableID = X
and JT.ColumnName3 = Y
para obtener más código en un área de visualización más pequeña. También creo que las palabras clave deben estar en mayúsculas
Mejor tarde que nunca. Utilizo un estilo diferente y lo adopté de un muy buen desarrollador de SQL con el que solía trabajar. Alineo correctamente las palabras clave y utilizo las letras MAYÚSCULAS para facilitar la escritura. Las palabras clave serán resaltadas por el editor y no veo la necesidad de que estén en MAYÚSCULAS a menos que haga mucha edición en editores de texto que no admite funciones de resaltado de palabras clave. No intento que sea compacto, sino más legible y alineado verticalmente tanto como sea posible. Aquí hay un ejemplo de selección tomada de @BenLaan respuesta escrita en mi formato:
select st.ColumnName1
, jt.ColumnName2
, sjt.ColumnName3
from SourceTable st
inner join
JoinTable jt
on jt.SourceTableID = st.SourceTableID
inner join
SecondJoinTable sjt
on st.SourceTableID = sjt.SourceTableID
and st.SourceTable2ID = sjt.SourceTable2ID
where st.SourceTableID = X
and jt.ColumnName3 = Y
and jt.Column3 = sjt.Column4
order by st.ColumnName1
Tratar de conformar a todo el equipo para seguir el mismo patrón de formateo es lo más difícil. Seguiría cualquier formato si todos los demás siguieran el mismo camino, pero nunca ha sido la misma historia.
ACTUALIZACIÓN: Reescribiendo una de las consultas complejas mencionadas en publicaciones anteriores:
select
term
, student_id
, case
when((ft_credits > 0 and credits >= ft_credits) or (ft_hours_per_week > 3 and hours_per_week >= ft_hours_per_week))
then ''F''
else ''P''
end as status
from (select term
, student_id
, pm.credits AS ft_credits
, pm.hours AS ft_hours_per_week
, SUM(credits) AS credits
, SUM(hours_per_week) AS hours_per_week
from (select e.term
, e.student_id
, nvl(o.credits, 0) credits
, case
when nvl(o.weeks, 0) > 5
then (nvl(o.lect_hours, 0) + nvl(o.lab_hours, 0) + nvl(o.ext_hours, 0)) / nvl(o.weeks, 0)
else 0
end as hours_per_week
from enrollment as e
inner join
offering as o using (term, offering_id)
inner join
program_enrollment as pe
on e.student_id = pe.student_id
and e.term = pe.term
and e.offering_id = pe.offering_id
where e.registration_code not in (''A7'', ''D0'', ''WL'')
)
inner join
student_history as sh using (student_id)
inner join
program_major as pm
on sh.major_code_1 = pm._major_code and sh.division_code_1 = pm.division_code
where sh.eff_term = (select max(eff_term)
from student_history as shi
where sh.student_id = shi.student_id
and shi.eff_term <= term)
group by term, student_id, pm.credits, pm.hours
)
order by term, student_id
Mi estilo preferido:
SELECT
ST.ColumnName1,
JT.ColumnName2,
SJT.ColumnName3
FROM
SourceTable ST
INNER JOIN
JoinTable JT
ON
JT.SourceTableID = ST.SourceTableID
INNER JOIN
SecondJoinTable SJT
ON
ST.SourceTableID = SJT.SourceTableID
WHERE
ST.SourceTableID = X
AND
JT.ColumnName3 = Y
AND
JT.Column3 = SJT.Column4
Nadie ha hecho expresiones comunes de tablas (CTE) todavía. A continuación lo incorpora junto con algunos otros estilos que uso:
@declare @tableVariable (
colA1 int,
colA2 int,
colB1 int,
colB2 nvarchar(255),
colB3 nvarchar(255),
colB4 int,
colB5 bit,
computed int
);
with
getSomeData as (
select st.colA1, sot.colA2
from someTable st
inner join someOtherTable sot on st.key = sot.key
),
getSomeOtherData as (
select colB1,
colB2,
colB3,
colB4,
colB5,
computed = case
when colB5 = 1 then ''here''
when colB5 = 2 then ''there''
end
from aThirdTable tt
inner hash
join aFourthTable ft
on tt.key1 = ft.key2
and tt.key2 = ft.key2
and tt.key3 = ft.key3
)
insert @tableVariable (
colA1, colA2, colA2,
colB1, colB2, colB3, colB4, colB5,
computed
)
select colA1, colA2,
colB1, colB2, colB3, colB4, colB5,
computed
from getSomeData data1
join getSomeOtherData data2
Algunos puntos en el formato CTE:
- En mi CTE "con" está en una línea separada, y todo lo demás en el cte está sangrado.
- Mis nombres de CTE son largos y descriptivos. Los CTE pueden ser complejos y los nombres descriptivos son muy útiles.
- Por alguna razón, me encuentro prefiriendo los verbos para los nombres CTE. Lo hace parecer más animado
- Estilo similar con los paréntesis como Javascript hace con sus llaves. También es así como hago las llaves en C #.
Esto simula:
func getSomeData() {
select st.colA1, sot.colA2
from someTable st
inner join someOtherTable sot on st.key = sot.key
}
Algunos puntos además del formato CTE:
- Dos pestañas después de "seleccionar" y otras palabras clave. Eso deja suficiente espacio para "unión interna", "agrupar por", etc. Puede ver un ejemplo anterior donde eso no es cierto. Pero la "combinación interna de hash" DEBE parecer fea. Sin embargo, en este punto, probablemente voy a experimentar con algunos de los estilos anteriores en el futuro.
- Las palabras clave son minúsculas. Su coloración por el IDE y su estado de indentación especial los resaltan lo suficiente. Me reservo mayúsculas para otras cosas que quiero enfatizar basadas en la lógica local (de negocios).
- Si hay pocas columnas, las pongo en una fila (getSomeData). Si hay algunos más, los verticalizo (getSomeOtherData). Si hay demasiada verticalización en una unidad, horizontalizo algunas columnas en la misma línea agrupada por lógica definida localmente (el segmento final de inserción y selección). Por ejemplo, pondría información de nivel escolar en una línea, nivel de estudiante en otra, etc.
- Especialmente cuando se está verticalizando, prefiero el nombre "varname = colname + something syntax" del servidor sql a "colname + something as varname".
- Duplique el último punto si estoy tratando con una declaración de caso.
- Si cierta lógica se presta a un estilo de ''matriz'', me ocuparé de las consecuencias del tipeo. Eso es más o menos lo que está sucediendo con la declaración del caso, donde los ''whens'' y ''then''s están alineados.
Encuentro que estoy más centrado en mi estilo CTE que en otras áreas. No he experimentado con los estilos más similares a los planteados en la pregunta. Probablemente lo haga algún día y vea cómo me gusta. Probablemente estoy maldito por estar en un ambiente donde es una elección, aunque es una maldición divertida de tener.
Sí, puedo ver el valor de diseñar su sql de una manera rigurosamente definida, pero seguramente la convención de nomenclatura y su intención son mucho más importantes. Como 10 veces más importante.
Basado en que mi mascota odia son las tablas con el prefijo tbl, y los procedimientos almacenados con el prefijo sp - sabemos que son tablas y SP. La denominación de objetos DB es mucho más importante que la cantidad de espacios que hay
Solo mi valor de $ 0.02
Si realizo cambios en T-SQL ya escrito, entonces sigo la convención ya usada (si la hay).
Si estoy escribiendo desde cero o no hay una convención, entonces tiendo a seguir su convención dada en la pregunta, excepto que prefiero usar mayúsculas para las palabras clave (solo una preferencia personal para la legibilidad).
Creo que con el formato SQL como con otras convenciones de formato de código, el punto importante es tener una convención, no lo que esa convención es (¡dentro de los dominios del sentido común, por supuesto!)
Soy de la opinión de que siempre que pueda leer el código fuente fácilmente, el formato es secundario. Siempre que se logre este objetivo, hay una serie de buenos estilos de diseño que pueden adoptarse.
El único otro aspecto que es importante para mí es que sea cual sea el diseño / estilo de codificación que elija adoptar en su tienda, asegúrese de que todos los programadores la utilicen de manera uniforme.
Solo para su referencia, aquí es cómo presentaría el ejemplo que proporcionó, solo mi preferencia de diseño. De particular interés, la cláusula ON está en la misma línea que la unión, solo la condición de unión primaria se enumera en la unión (es decir, la coincidencia de tecla) y otras condiciones se mueven al cluase de donde.
select
ST.ColumnName1,
JT.ColumnName2,
SJT.ColumnName3
from
SourceTable ST
inner join JoinTable JT on
JT.SourceTableID = ST.SourceTableID
inner join SecondJoinTable SJT on
ST.SourceTableID = SJT.SourceTableID
where
ST.SourceTableID = X
and JT.ColumnName3 = Y
and JT.Column3 = SJT.Column4
Un consejo: obtén una copia de SQL Prompt de Red Gate. Puede personalizar la herramienta para usar las preferencias de diseño deseadas y, a continuación, los programadores de su tienda pueden usarla para garantizar que todos adopten los mismos estándares de codificación.
Sugeriría el siguiente estilo, basado en la sugerencia de John:
/*
<Query title>
<Describe the overall intent of the query>
<Development notes, or things to consider when using/interpreting the query>
*/
select
ST.ColumnName1,
JT.ColumnName2,
SJT.ColumnName3
from
-- <Comment why this table is used, and why it''s first in the list of joins>
SourceTable ST
-- <Comment why this join is made, and why it''s an inner join>
inner join JoinTable JT
on ST.SourceTableID = JT.SourceTableID
-- <Comment why this join is made, and why it''s an left join>
left join SecondJoinTable SJT
on ST.SourceTableID = SJT.SourceTableID
and JT.Column3 = SJT.Column4
where
-- comment why this filter is applied
ST.SourceTableID = X
-- comment why this filter is applied
and JT.ColumnName3 = (
select
somecolumn
from
sometable
)
;
Ventajas:
- Los comentarios son una parte esencial para hacer que el código sea legible y para detectar errores.
- Agregar -todos los filtros "a" a la unión evita errores al cambiar de unión interna a izquierda.
- Colocar el punto y coma en una nueva línea permite añadir / comentar fácilmente las cláusulas where.
Tarde, pero voy a lanzar mi sombrero en el ring. Lleva un poco más de tiempo escribir, pero descubro que surgen patrones con la alineación vertical que lo hacen muy legible una vez que está acostumbrado.
SELECT ST.ColumnName1,
JT.ColumnName2,
SJT.ColumnName3,
CASE WHEN condition1 = True
AND condition2 = True Then DoSomething
Else DoSomethingElse
END ColumnName4
FROM SourceTable AS ST
INNER
JOIN JoinTable AS JT
ON JT.SourceTableID = ST.SourceTableID
INNER
JOIN SecondJoinTable AS SJT
ON ST.SourceTableID = SJT.SourceTableID
AND JT.Column3 = SJT.Column4
LEFT
JOIN (SELECT Column5
FROM Table4
QUALIFY row_number() OVER
( PARTITION BY pField1,
pField2
ORDER BY oField1
) = 1
) AS subQry
ON SJT.Column5 = subQry.Column5
WHERE ST.SourceTableID = X
AND JT.ColumnName3 = Y
Tiendo a usar un diseño similar al suyo, aunque incluso voy unos pasos más allá, por ejemplo:
select
ST.ColumnName1
, JT.ColumnName2
, SJT.ColumnName3
from
SourceTable ST
inner join JoinTable JT
on JT.SourceTableID = ST.SourceTableID
inner join SecondJoinTable SJT
on ST.SourceTableID = SJT.SourceTableID
where
ST.SourceTableID = X
and JT.ColumnName3 = Y
and JT.Column3 = SJT.Column4
Tal vez se vea un poco exagerado al principio, pero en mi humilde opinión, el uso de la tabulación proporciona el diseño más limpio y sistemático dada la naturaleza declarativa de SQL.
Probablemente termines con todo tipo de respuestas aquí, al final depende de las preferencias personales o del equipo acordado.
Utilizo un formato similar al tuyo, excepto que puse la palabra clave "ON" en la misma línea que la unión y puse los operadores "AND" y "OR" al final de las líneas para que todos mis criterios de unión / selección se alineen bien.
Si bien mi estilo es similar al de John Sansom, no estoy de acuerdo con poner criterios de unión en la cláusula WHERE. Creo que debería ser con la tabla unida para que esté organizada y sea fácil de encontrar.
También tiendo a poner paréntesis en líneas nuevas, alineado con la línea de arriba y luego sangrando en la línea siguiente, aunque para las declaraciones cortas puedo mantener los paréntesis en la línea original. Por ejemplo:
SELECT
my_column
FROM
My_Table
WHERE
my_id IN
(
SELECT
my_id
FROM
Some_Other_Table
WHERE
some_other_column IN (1, 4, 7)
)
Para las sentencias CASE doy una nueva línea y sangría para cada WHEN y ELSE y alineo el END de nuevo con CASE:
CASE
WHEN my_column = 1 THEN ''one''
WHEN my_column = 2 THEN ''two''
WHEN my_column = 3 THEN ''three''
WHEN my_column = 4 THEN ''four''
ELSE ''who knows''
END
Yo uso Red Gate SQL ReFactor dentro de SSMS, pero otra herramienta que hace reformas (y es un reemplazo para SSMS) es Apex''s SQL Edit . Si está buscando publicar código en línea, existe The Simple-Talk SQL Prettifier .
Respuesta tardía pero con suerte útil
Mi experiencia trabajando como parte del equipo de desarrollo más grande es que puedes seguir adelante y definir los estándares que te gusten, pero el problema es hacerlos cumplir o hacer que sea muy fácil de implementar para los desarrolladores.
Como desarrolladores, a veces creamos algo que funciona y luego decimos "Voy a formatearlo más tarde", pero eso luego nunca llega.
Inicialmente usamos SQL Prompt (fue genial) para esto, pero luego cambiamos a ApexSQL Refactor porque es una herramienta gratuita.
Cien respuestas aquí ya, pero después de mucho ir y venir en los últimos años, esto es lo que he decidido por:
SELECT ST.ColumnName1
, JT.ColumnName2
, SJT.ColumnName3
FROM SourceTable ST
JOIN JoinTable JT ON JT.SourceTableID = ST.SourceTableID
JOIN SecondJoinTable SJT ON ST.SourceTableID = SJT.SourceTableID
AND JT.Column3 = SJT.Column4
WHERE ST.SourceTableID = X
AND JT.ColumnName3 = Y
Sé que esto puede hacer para ficheros diff desordenado como una mesa adicional podría causar mí para volver a sangrar muchas líneas de código, pero para mi facilitar la lectura, me gusta.
Parece ser que la mayoría de ustedes todavía trabajan en los monitores que sólo soportan 800x600. Mis monitores harán 1920x1080, así que quiero utilizar todo ese espacio a la derecha.
Qué tal esto:
select col1, col2, col3
, case when x = 1 then ''answer1''
else ''answer2''
end
, col4, col5, col6, col7
from table1 t1
inner join table2 t2 on t1.col1 = t2.col1 and t1.col2 and t2.col2
where t1.col5 = 19 and t1.col7 = ''Bill Gates''
SELECT
a.col1 AS [Column1]
,b.col2 AS [Column2]
,c.col1 AS [Column3]
FROM
Table1 a
INNER JOIN Table2 b ON b.Id = a.bId
INNER JOIN Table3 c ON c.Id = a.cId
WHERE
a.col = X
AND b.col = Y
Utiliza muchas más líneas que muchos de los ejemplos aquí, pero creo que es mucho más fácil de entender, permite la eliminación rápida de columnas / cláusulas / tablas. Ayuda a aprovechar un monitor orientado verticalmente.
SELECT st.ColumnName1
,jt.ColumnName2
,sjt.ColumnName3
FROM SourceTable st
JOIN JoinTable jt ON jt.SourceTableID = st.SourceTableID
JOIN SecondJoinTable sjt ON SstT.SourceTableID = sjt.SourceTableID
AND jt.Column3 = sjt.Column4
WHERE st.SourceTableID = X
AND jt.ColumnName3 = Y
Yo uso todas las tapas de las palabras acciones, se une o cláusulas, se destacan mejor. JOIN es el mismo que el INNER JOIN por lo interior no necesita ser escrita a cabo, se supone, escribir OUTER JOIN o LEFT JOIN cuando lo necesite. También uso lowere caso de mis nombres de alias. causa común frente a cabo si se comente la última columna que hay que contentarse con una coma arriba y la consulta falla.