Por que os curingas nas instruções GROUP BY não funcionam?


29

Estou tentando fazer com que a seguinte instrução SQL funcione, mas recebo um erro de sintaxe:

SELECT A.*, COUNT(B.foo)
FROM TABLE1 A
LEFT JOIN TABLE2 B ON A.PKey = B.FKey
GROUP BY A.*

Aqui, A é uma tabela ampla com 40 colunas e eu gostaria de evitar listar o nome de cada coluna na cláusula GROUP BY, se possível. Eu tenho muitas dessas tabelas nas quais tenho que executar uma consulta semelhante, então terei que escrever um Procedimento Armazenado. Qual é a melhor maneira de abordar isso?

Estou usando o MS SQL Server 2008.

Respostas:


32

GROUP BY A.* não é permitido no SQL.

Você pode contornar isso usando uma subconsulta na qual agrupa e depois ingressar em:

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 ;

Há um recurso no padrão SQL-2003 para permitir na SELECTlista colunas que não estão na GROUP BYlista, desde que sejam funcionalmente dependentes delas. Se esse recurso tivesse sido implementado no SQL-Server, sua consulta poderia ter sido escrita 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

Infelizmente, esse recurso ainda não foi implementado, nem na versão SQL-Server 2012 - e em nenhum outro DBMS, até onde eu saiba. Exceto pelo MySQL que o possui, mas inadequadamente (inadequadamente, como: a consulta acima funcionará, mas o mecanismo não verificará a dependência funcional e outras consultas incorretas mostrarão resultados semi-aleatórios errados).

Como o @Mark Byers nos informou em um comentário, o PostgreSQL 9.1 adicionou um novo recurso desenvolvido para essa finalidade. É mais restritivo que a implementação do MySQL.


Você pode mencionar alguns RDBMSs que implementam essa parte do padrão conforme escrito? Eu sei, por exemplo, que o MySQL permitirá que você (com as configurações apropriadas) inclua itens que não estão dentro da GROUP BYcláusula na SELECTlista, mas deixa indefinido para qual linha esse valor virá (portanto, se a coluna ou expressão não for 't funcionalmente dependente da expressão de agrupamento, então ele pode vir de qualquer linha dentro do grupo).
11138 Adam Robinson

@ Adam: Não, não conheço nenhum RDBMS que o implemente. O MySQL possui, mas inadequadamente, como diz o seu comentário.
ypercubeᵀᴹ

Peguei vocês. Na verdade, eu estava perguntando se havia, já que tenho experiência com muito menos RDBMSs do que eu imaginaria que a maioria das pessoas que respondeu às perguntas neste site teria;) Mas essa era minha suspeita.
11138 Adam Robinson

3
"e não em nenhum outro SGBD, tanto quanto eu saiba." O PostgreSQL 9.1 adicionou um novo recurso projetado para esse fim. É mais restritivo que a implementação do MySQL.
21812 Mark Byers

@ MarkByers: thnx, eu não sabia disso.
precisa saber é o seguinte

24

Além da solução alternativa do @ ypercube, "digitar" nunca é uma desculpa para usar SELECT *. Eu tenho escrito sobre este aqui , e mesmo com a solução que eu acho que a sua SELECTlista ainda deve incluir os nomes das colunas - mesmo se houver um grande número como 40.

Para encurtar a história, você pode evitar digitar essas grandes listas clicando e arrastando o nó Colunas do objeto no Pesquisador de Objetos para a janela de consulta. A captura de tela mostra uma vista, mas o mesmo pode ser feito para uma mesa.

insira a descrição da imagem aqui

Mas se você quiser ler sobre todas as razões pelas quais deve se sujeitar a esse enorme nível de esforço de arrastar um item alguns centímetros, leia meu post . :-)


No PostgreSQL (com o EMS SQL Manager), faço isso definindo uma exibição como SELECT *e copio a lista de campos da definição de exibição.
Dezso

Eu certamente concordo que SELECT *não deve ser usado. Estou curioso sobre o GROUP BYcaso. @ Aaron, há problemas de eficiência em ter 40 colunas na lista Agrupar por?
ypercubeᵀᴹ

1
@ypercube - Até onde eu já vi, se você agrupar por A.PK, A.some, A.other, A.columnsele, não se incomoda em comparar some, other, columnsisso, apenas é exigido pela sintaxe.
Martin Smith

1
@datagod desculpe, não, quaisquer lacunas só poderiam ser explicadas pela equipe de desenvolvedores do SSMS. :-)
Aaron Bertrand

1
@ Pacerier Desculpe, eu discordo completamente , mas talvez você possa elaborar.
Aaron Bertrand
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.