Em consultas SQL, usamos a cláusula Group by para aplicar funções agregadas.
- Mas qual é o propósito de usar o valor numérico em vez do nome da coluna com a cláusula Group by? Por exemplo: Agrupar por 1.
Comentários
Resposta
Isso é realmente muito ruim coisa a fazer IMHO e “não é suportado na maioria das outras plataformas de banco de dados.
Os motivos pelos quais as pessoas fazem isso:
- eles são preguiçosos – Não sei por que as pessoas acham que sua produtividade é melhorada escrevendo um código conciso em vez de digitar por mais 40 milissegundos para obter um código muito mais literal.
Os motivos pelos quais é ruim:
-
não é autodocumentado – alguém terá que analisar a lista do SELECT para descobrir o agrupamento. Na verdade, seria um pouco mais claro no SQL Server, que não oferece suporte a cowboy que- agrupamento sabe-o-que-vai-acontecer como o MySQL faz.
-
é “frágil – alguém entra e muda a lista do SELECT porque os usuários de negócios queriam uma saída de relatório diferente e agora sua saída está uma bagunça. Se você tivesse usado nomes de coluna em GROUP BY, a ordem na lista SELECT seria irrelevante.
O SQL Server oferece suporte a ORDER BY [ordinal]; aqui estão alguns argumentos paralelos contra seu uso:
Resposta
O MySQL permite que você faça GROUP BY
com aliases ( Problemas com aliases de coluna ). Isso seria muito melhor do que fazer GROUP BY
com números.
- Algumas pessoas ainda ensinam
- Alguns têm
column number
em diagramas SQL . Uma linha diz: Classifica o resultado pelo número da coluna fornecida ou por uma expressão. Se a expressão for um único parâmetro, o valor será interpretado como um número de coluna. Números de coluna negativos invertem a ordem de classificação. - O Apache suspendeu seu uso porque o SQL Server o fez
O Google tem muitos exemplos de uso e por que muitos pararam de usá-lo.
Para ser honesto com você, não usei números de coluna para ORDER BY
e GROUP BY
desde 1996 (eu estava fazendo Oracle PL / SQL Development na época). Usar números de coluna é realmente para veteranos e a compatibilidade com versões anteriores permite que esses desenvolvedores usem MySQL e outros RDBMSs ainda permita.
Resposta
Considere o caso abaixo:
+------------+--------------+-----------+ | date | services | downloads | +------------+--------------+-----------+ | 2016-05-31 | Apps | 1 | | 2016-05-31 | Applications | 1 | | 2016-05-31 | Applications | 1 | | 2016-05-31 | Apps | 1 | | 2016-05-31 | Videos | 1 | | 2016-05-31 | Videos | 1 | | 2016-06-01 | Apps | 3 | | 2016-06-01 | Applications | 4 | | 2016-06-01 | Videos | 2 | | 2016-06-01 | Apps | 2 | +------------+--------------+-----------+
Você deve descobrir o número de downloads por serviço por dia, considerando Aplicativos e Aplicativos como o mesmo serviço. O agrupamento por date, services
resultaria em Apps
e Applications
sendo considerados serviços separados.
Nesse caso, a consulta seria:
select date, services, sum(downloads) as downloads from test.zvijay_test group by date,services
E saída:
+------------+--------------+-----------+ | date | services | downloads | +------------+--------------+-----------+ | 2016-05-31 | Applications | 2 | | 2016-05-31 | Apps | 2 | | 2016-05-31 | Videos | 2 | | 2016-06-01 | Applications | 4 | | 2016-06-01 | Apps | 5 | | 2016-06-01 | Videos | 2 | +------------+--------------+-----------+
Mas isso não é o que você deseja, pois o agrupamento de Aplicativos e Aplicativos é o requisito. Então, o que podemos fazer?
Uma maneira é substituir Apps
por Applications
usando um CASE
expressão ou a função IF
e agrupá-los nos serviços como:
select date, if(services="Apps","Applications",services) as services, sum(downloads) as downloads from test.zvijay_test group by date,services
Mas isso ainda agrupa serviços considerando Apps
e Applications
como serviços diferentes e dá a mesma saída de antes:
+------------+--------------+-----------+ | date | services | downloads | +------------+--------------+-----------+ | 2016-05-31 | Applications | 2 | | 2016-05-31 | Applications | 2 | | 2016-05-31 | Videos | 2 | | 2016-06-01 | Applications | 4 | | 2016-06-01 | Applications | 5 | | 2016-06-01 | Videos | 2 | +------------+--------------+-----------+
O agrupamento sobre um número de coluna permite agrupar dados em uma coluna com alias.
select date, if(services="Apps","Applications",services) as services, sum(downloads) as downloads from test.zvijay_test group by date,2;
E assim dando a você a saída desejada conforme abaixo:
+------------+--------------+-----------+ | date | services | downloads | +------------+--------------+-----------+ | 2016-05-31 | Applications | 4 | | 2016-05-31 | Videos | 2 | | 2016-06-01 | Applications | 9 | | 2016-06-01 | Videos | 2 | +------------+--------------+-----------+
Eu “ve li muitas vezes que esta é uma maneira preguiçosa de escrever consultas ou agrupar sobre uma coluna com alias não funciona no MySQL, mas esta é a maneira de agrupar sobre colunas com alias.
Esta não é a maneira preferida de escrever consultas, use-a apenas quando você realmente precisa agrupar em uma coluna com alias.
Comentários
- " Mas isso ainda agrupa os serviços considerando Apps e Aplicativos como serviços diferentes e dá a mesma saída que anteriormente ".Não ' isso seria resolvido se você ' tivesse escolhido um nome diferente (não conflitante) para o alias?
- @ Daddy32 Exatamente meu pensamento. Ou até mesmo aninhe mais uma vez (agrupe após selecionar)
Resposta
Não há razão válida para usá-lo. É simplesmente um atalho preguiçoso especialmente projetado para dificultar para algum desenvolvedor pressionado a descobrir seu agrupamento ou classificação posteriormente ou para permitir que o código falhe terrivelmente quando alguém altera a ordem das colunas. Tenha consideração pelos seus colegas desenvolvedores e não faça isso.
Resposta
Isso funcionou para mim. O código agrupa o linhas até 5 grupos.
SELECT USR.UID, USR.PROFILENAME, ( CASE WHEN MOD(@curRow, 5) = 0 AND @curRow > 0 THEN @curRow := 0 ELSE @curRow := @curRow + 1 /*@curRow := 1*/ /*AND @curCode := USR.UID*/ END ) AS sort_by_total FROM SS_USR_USERS USR, ( SELECT @curRow := 0, @curCode := "" ) rt ORDER BY USR.PROFILENAME, USR.UID
O resultado será o seguinte
Resposta
SELECT dep_month,dep_day_of_week,dep_date,COUNT(*) AS flight_count FROM flights GROUP BY 1,2; SELECT dep_month,dep_day_of_week,dep_date,COUNT(*) AS flight_count FROM flights GROUP BY 1,2,3;
Considere as consultas acima: Agrupar por 1 significa agrupar pela primeira coluna e agrupar por 1,2 significa agrupar pela primeira e segunda colunas e agrupar por 1,2,3 significa agrupar pela primeira, segunda e terceira colunas. Por exemplo:
esta imagem mostra as duas primeiras colunas agrupadas por 1,2, ou seja, não está considerando os diferentes valores de dep_date para encontrar a contagem (para calcular a contagem, todas as combinações distintas das duas primeiras colunas são levadas em consideração) enquanto a segunda consulta resulta em
imagem. Aqui, ele está considerando todas as três primeiras colunas e há diferentes valores para encontrar a contagem, ou seja, está agrupando por todas as três primeiras colunas (para calcular a contagem, todas as combinações distintas das três primeiras colunas são levadas em consideração).
order by 1
apenas quando estiver sentado no promptmysql>
. No código, useORDER BY id ASC
. Observe o caso, o nome de campo explícito e a direção de ordenação explícita.