Por que usamos Agrupar por 1 e Agrupar por 1,2,3 na consulta SQL?

26

Nas consultas SQL, usamos a cláusula Group by para aplicar funções agregadas.

  • Mas qual é o objetivo por trás do uso de valor numérico em vez do nome da coluna com a cláusula Agrupar por? Por exemplo: Agrupe por 1.
ursitesion
fonte
3
Use order by 1apenas quando estiver sentado no mysql> prompt. No código, use ORDER BY id ASC. Observe o caso, o nome explícito do campo e a direção explícita da ordem.
dotancohen

Respostas:

28

Isso é realmente uma coisa muito ruim para se fazer IMHO, e não é suportado na maioria das outras plataformas de banco de dados.

As razões pelas quais as pessoas fazem isso:

  • eles são preguiçosos - não sei por que as pessoas pensam que sua produtividade é melhorada escrevendo código conciso em vez de digitar por mais 40 milissegundos para obter um código muito mais literal.

As razões são ruins:

  • não é auto-documentado - alguém precisará analisar a lista SELECT para descobrir o agrupamento. Na verdade, seria um pouco mais claro no SQL Server, que não suporta agrupamentos de quem sabe o que vai acontecer como o MySQL.

  • é frágil - alguém entra e altera a lista SELECT porque os usuários corporativos queriam uma saída de relatório diferente e agora sua saída está uma bagunça. Se você tivesse usado nomes de colunas no 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:

Aaron Bertrand
fonte
9

O MySQL permite que você faça GROUP BYaliases ( Problemas com aliases de colunas ). Isso seria muito melhor do que fazer GROUP BYcom números.

O Google tem muitos exemplos de como usá-lo e por que muitos pararam de usá-lo.

Para ser honesto com você, eu não usei números das colunas para ORDER BYe GROUP BYdesde 1996 (eu estava fazendo Oracle PL / SQL Desenvolvimento na época). O uso de números de coluna é realmente para veteranos e a compatibilidade com versões anteriores permite que esses desenvolvedores usem o MySQL e outros RDBMSs que ainda o permitem.

RolandoMySQLDBA
fonte
8

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ê precisa descobrir o número de downloads por serviço por dia, considerando aplicativos e aplicativos como o mesmo serviço. O agrupamento por date, servicesresultaria Appse Applicationsseria considerado um serviço separado.

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 não é isso que você deseja, pois o agrupamento de aplicativos e aplicativos é o requisito. Então o que nós podemos fazer?

Uma maneira é substituir Appspelo Applicationsuso de uma CASEexpressão ou IFfunção e agrupá-los em 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 Appse Applicationscomo serviços diferentes e fornece a mesma saída que anteriormente:

+------------+--------------+-----------+
| 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 o número de uma 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, fornecendo a saída desejada, como 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 já li muitas vezes que essa é uma maneira lenta de escrever consultas ou agrupar sobre uma coluna com alias não funciona no MySQL, mas essa é a maneira de agrupar colunas com alias.

Essa não é a maneira preferida de escrever consultas, use-a apenas quando você realmente precisar agrupar sobre uma coluna com alias.

imVJ
fonte
" Mas isso ainda agrupa serviços considerando Aplicativos e aplicativos como serviços diferentes e produz a mesma saída que anteriormente ". Isso não seria resolvido se você tivesse escolhido um nome diferente (não conflitante) para o alias?
precisa saber é o seguinte
3

Não há motivo válido para usá-lo. É simplesmente um atalho lento, especialmente projetado para dificultar a algum desenvolvedor pressionado descobrir seu agrupamento ou classificação posteriormente ou permitir que o código falhe miseravelmente quando alguém altera a ordem das colunas. Seja atencioso com seus colegas desenvolvedores e não faça isso.

BriteSponge
fonte
0

Isso é trabalhado para mim. O código agrupa as linhas em 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

insira a descrição da imagem aqui

navio shuk - www.shipshuk.com
fonte
0
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 coluna e agrupar por 1,2,3 significa agrupar pela primeira segunda e terceira coluna. Por exemplo:

agrupar por 1,2

esta imagem mostra as duas primeiras colunas agrupadas por 1,2, isto é, 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 agrupar por 1,2,3

imagem. Aqui estão considerando todas as três primeiras colunas e existem valores diferentes para encontrar a contagem, ou seja, é agrupado pelas três primeiras colunas (para calcular a contagem, todas as combinações distintas das três primeiras colunas são levadas em consideração).

codificador
fonte