¿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
LEFT JOIN TABLE2 B ON A.PKey = B.FKey
GROUP BY 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?

Estoy usando MS SQL Server 2008.

Respuestas:


32

GROUP BY A.* no está permitido en SQL.

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
  LEFT JOIN 
      ( SELECT FKey, COUNT(foo) AS cnt
        FROM TABLE2 
        GROUP BY 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
LEFT JOIN TABLE2 B ON A.PKey = B.FKey
GROUP BY 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).

Como @Mark Byers nos informó en un comentario, PostgreSQL 9.1 agregó una nueva característica diseñada para este propósito. Es más restrictivo que la implementación de MySQL.


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

ingrese la descripción de la imagen aquí

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. :-)
Aaron Bertrand

1
@Pacerier Lo siento, no estoy de acuerdo por completo , pero tal vez podrías dar más detalles.
Aaron Bertrand
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.