¿Por qué los comodines en las declaraciones GROUP BY no funcionan?
29
Estoy tratando de hacer que funcione la siguiente instrucción SQL, pero aparece un error de sintaxis:
SELECT A.*, COUNT(B.foo)FROM TABLE1 A
LEFTJOIN TABLE2 B ON A.PKey = B.FKey
GROUPBY A.*
Aquí, A es una tabla amplia con 40 columnas y me gustaría evitar enumerar cada nombre de columna en la cláusula GROUP BY si es posible. Tengo muchas de esas tablas sobre las que tengo que ejecutar una consulta similar, por lo que tendré que escribir un Procedimiento almacenado. ¿Cuál es la mejor manera de abordar esto?
Puede omitir esto utilizando una subconsulta donde agrupe y luego se una:
SELECT A.*,COALESCE(B.cnt,0)AS Count_B_Foo
FROM TABLE1 AS A
LEFTJOIN(SELECT FKey, COUNT(foo)AS cnt
FROM TABLE2
GROUPBY FKey
)AS B
ON A.PKey = B.FKey ;
Hay una característica en el estándar SQL-2003 para permitir en la SELECTlista, columnas que no están en la GROUP BYlista, siempre que sean funcionalmente dependientes de ellas. Si esa característica se hubiera implementado en SQL-Server, su consulta podría haberse escrito como:
SELECT A.*, COUNT(B.foo)FROM TABLE1 A
LEFTJOIN TABLE2 B ON A.PKey = B.FKey
GROUPBY A.pk --- the Primary Key of table A
Desafortunadamente, esta característica aún no se ha implementado, ni siquiera en la versión SQL-Server 2012, y no en ningún otro DBMS, que yo sepa. Excepto para MySQL que lo tiene pero de manera inadecuada (de manera inadecuada como: la consulta anterior funcionará pero el motor no verificará la dependencia funcional y otras consultas mal escritas mostrarán resultados semialeatorios incorrectos).
¿Puede mencionar un par de RDBMS que implementen esa parte del estándar tal como está escrito? Sé, por ejemplo, que MySQL le permitirá (dada la configuración adecuada) incluir elementos que no están dentro de la GROUP BYcláusula en la SELECTlista, pero lo deja sin definir de qué fila vendrá ese valor (por lo tanto, si la columna o expresión no es 't funcionalmente dependiente de la expresión de agrupación, entonces podría venir de cualquier fila dentro del grupo).
Adam Robinson
@ Adam: No, no conozco ningún RDBMS que lo tenga implementado. MySQL lo tiene pero de manera inadecuada, como dice su comentario.
ypercubeᵀᴹ
Gotcha En realidad, estaba preguntando si los había, ya que tengo experiencia con muchos menos RDBMS de los que imagino que la mayoría de las personas que respondieron preguntas en este sitio tendrían;) Pero esa era mi sospecha.
Adam Robinson
3
"y no en ningún otro DBMS que yo sepa". PostgreSQL 9.1 agregó una nueva característica diseñada para este propósito. Es más restrictivo que la implementación de MySQL.
Mark Byers
@ MarkByers: gracias, no lo sabía.
ypercubeᵀᴹ
24
Además de la solución alternativa de @ ypercube, "escribir" nunca es una excusa para usar SELECT *. He escrito sobre esto aquí , e incluso con la solución alternativa, creo que su SELECTlista aún debe incluir los nombres de columna, incluso si hay un número masivo como 40.
Para resumir, puede evitar escribir estas grandes listas haciendo clic y arrastrando el nodo Columnas para el objeto en el Explorador de objetos a su ventana de consulta. La captura de pantalla muestra una vista, pero se puede hacer lo mismo para una tabla.
Pero si desea leer sobre todas las razones por las que debería someterse a este gran nivel de esfuerzo de arrastrar un elemento unas pocas pulgadas, lea mi publicación . :-)
En PostgreSQL (con EMS SQL Manager), hago esto definiendo una vista como SELECT *y luego copio la lista de campos de la definición de vista.
dezso
Ciertamente estoy de acuerdo en que SELECT *no debe usarse. Aunque tengo curiosidad sobre el GROUP BYcaso. @ Aaron, ¿hay problemas de eficiencia al tener 40 columnas en la lista Agrupar por?
ypercubeᵀᴹ
1
@ypercube: por lo que he visto, si agrupas por A.PK, A.some, A.other, A.columnsél no molesta en realidad comparar some, other, columnsesto solo es requerido por la sintaxis.
Martin Smith
1
@datagod lo siento, no, las brechas solo pueden ser explicadas por el equipo de desarrollo de SSMS. :-)
GROUP BY
cláusula en laSELECT
lista, pero lo deja sin definir de qué fila vendrá ese valor (por lo tanto, si la columna o expresión no es 't funcionalmente dependiente de la expresión de agrupación, entonces podría venir de cualquier fila dentro del grupo).Además de la solución alternativa de @ ypercube, "escribir" nunca es una excusa para usar
SELECT *
. He escrito sobre esto aquí , e incluso con la solución alternativa, creo que suSELECT
lista aún debe incluir los nombres de columna, incluso si hay un número masivo como 40.Para resumir, puede evitar escribir estas grandes listas haciendo clic y arrastrando el nodo Columnas para el objeto en el Explorador de objetos a su ventana de consulta. La captura de pantalla muestra una vista, pero se puede hacer lo mismo para una tabla.
Pero si desea leer sobre todas las razones por las que debería someterse a este gran nivel de esfuerzo de arrastrar un elemento unas pocas pulgadas, lea mi publicación . :-)
fuente
SELECT *
y luego copio la lista de campos de la definición de vista.SELECT *
no debe usarse. Aunque tengo curiosidad sobre elGROUP BY
caso. @ Aaron, ¿hay problemas de eficiencia al tener 40 columnas en la lista Agrupar por?A.PK, A.some, A.other, A.columns
él no molesta en realidad compararsome, other, columns
esto solo es requerido por la sintaxis.