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
LEFTJOIN TABLE2 B ON A.PKey = B.FKey
GROUPBY 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?
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
LEFTJOIN(SELECT FKey, COUNT(foo)AS cnt
FROM TABLE2
GROUPBY 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
LEFTJOIN TABLE2 B ON A.PKey = B.FKey
GROUPBY 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).
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.
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. :-)
GROUP BY
cláusula naSELECT
lista, 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).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 suaSELECT
lista 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.
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 . :-)
fonte
SELECT *
e copio a lista de campos da definição de exibição.SELECT *
não deve ser usado. Estou curioso sobre oGROUP BY
caso. @ Aaron, há problemas de eficiência em ter 40 colunas na lista Agrupar por?A.PK, A.some, A.other, A.columns
ele, não se incomoda em compararsome, other, columns
isso, apenas é exigido pela sintaxe.