Estou aprendendo SQL e criei o seguinte conjunto de dados no MySQL:
Create table Departments (DepartmentID int primary key, Name text);
insert into Departments values
(1001,'SRO'),
(2001,'Drs'),
(3001,'Accounting');
Create table Employees
(
EmployeeID int not null,
DepartmentID int not null,
ManagerID int,
Name varchar(50) not null,
Salary int not null,
primary key(EmployeeID),
foreign key (DepartmentID)
references Departments(DepartmentID)
);
insert into Employees values
(68319,1001,NULL,'Kayling','6000.00'),
(66928,3001,68319,'Blaze','2750.00'),
(67832,1001,68319,'Clare','2550.00'),
(65646,2001,68319,'Jonas','2957.00'),
(67858,2001,65646,'Scarlet','3100.00'),
(69062,2001,65646,'Frank','3100.00'),
(63679,2001,69062,'Sandrine','900.00'),
(64989,3001,66928,'Adelyn','1700.00'),
(65271,3001,66928,'Wade','1350.00');
Quero descobrir o salário máximo para cada departamento, pesquisando muitos dos artigos que vi sugeridos MAX
neste formulário:
SELECT max(Salary),DepartmentID
FROM Employees
GROUP BY DepartmentID;
No entanto, dada a ordem das operações descritas na resposta aqui
FROM, including JOINs
WHERE
SELECT the row obtained by from and where in a temporary area for others
operation (and build the column alias)
DISTINCT
GROUP BY
HAVING
ORDER BY
LIMIT and OFFSET
return the final result
A MAX
função é chamada antes de GROUP BY
, o que significa que MAX
funcionará em toda a tabela antes GROUP BY
mesmo de ser executada, o que, no meu entendimento, deve resultar na presença de um único valor máximo em toda a tabela , que deve ser 6000 . No entanto, não é isso que acontece, os resultados que vejo estão confusos na estrutura certa que desejo:
max(Salary) DepartmentID
6000 1001
3100 2001
2750 3001
de alguma forma, a MAX
função funciona depois de a GROUP BY
, mas também antes de perder todas as linhas devido à GROUP BY
eliminação de várias linhas do grupo.
Se eu prosseguir com esse entendimento, surgirão mais perguntas para mim.
Se uma GROUP BY
operação ocorrer antes de SELECT
, então ele GROUP BY
removerá todas as linhas de cada um DepartmentID
e deixará apenas uma única linha escolhida aleatoriamente , o que significa que no momento em que a MAX
função SELECT
tiver a chance de ser executada, ela verá apenas um valor de salário que pode ser qualquer valor em vez do máximo para cada departamento.
O que estou perdendo que está complicando meu entendimento?
Funções agregadas como MAX (ou SUM, MIN, COUNT etc) são aplicadas aos conjuntos criados pela
GROUP BY
cláusula.No seu exemplo, os salários de cada departamento são divididos em conjuntos separados e a função MAX é aplicada a cada conjunto, fornecendo o salário máximo para cada departamento.
O que precisamos entender quando avaliamos uma consulta é que há uma projeção antes
group by
e uma projeção depois degroup by
.Antes de
group by
definirmos de que relação devemos agrupar. Pode ser uma tabela inteira, uma tabela projetada (as colunas são diferentes das inicialmente definidas), uma tabela filtrada (where
cláusulas e junções) ou mesmo uma tabela ad-hoc (como (select 1 as foo union select 2 as foo union select 3 as foo
)).GROUP BY
é o processo de agregação dos resultados. Isso significa que coisas comoMAX()
ouMIN()
,AVG()
por padrão (não obstante os índices) não são avaliáveis antes que os registros que contribuem para o resultado não sejam avaliados completamente.Então, como você avaliaria o valor MAX de algo, por exemplo:
(pseudo-código)
e é isso que acontece no seu caso.
MAX(yourfield)
marca que para este campo você precisa descobrir qual é o máximo para o conjunto de resultados. E se houvesse umGROUP BY
, então o pseudocódigo muda para algo assim:Assim, os registros são desagrupados e estão sendo processados. À medida que os grupos vão sendo construídos, os valores agregados separados vão sendo construídos separadamente.