SQL 在 Oracle HR 模式中
SQL in Oracle HR Schema
我在 Oracle HR 模式中进行了查询以查看以下信息:
- 部门所在城市
- 部门员工总数
然而,查询无法正确执行并表示这“不是 GROUP BY 表达式”。
有谁知道问题出在哪里?提前致谢。
SELECT department_name, city, COUNT(employees.department_id)
FROM departments
JOIN employees on (departments.department_id=employees.department_id)
JOIN locations USING (location_id)
GROUP BY department_name;
问题是您同时拥有聚合列和 non-aggregated 列(在您的情况下 city
在 select 列表中。
因为我不知道位置 table 的结构并且考虑到 department
只有一个 location
定义你可以使用 max(city)
,
SELECT department_name, max(city) city, COUNT(employees.department_id) no_of_employees
FROM departments
JOIN employees on (departments.department_id=employees.department_id)
JOIN locations USING (location_id)
GROUP BY department_name;
您正在按部门分组并希望显示部门所在的城市。您希望这会起作用,因为每个部门都在一个城市。 (SQL 人们称之为函数依赖。)
要实现这一点,...
- 部门名称必须有唯一约束,否则您必须按 department_id 分组
- DBMS 必须检测并支持聚合查询中的函数依赖性
遗憾的是,Oracle 不支持聚合查询中的函数依赖。它迫使我们将每个这样的列放在 GROUP BY
子句或聚合函数中。
所以要么扩展 GROUP BY
子句:
SELECT d.department_name, l.city, COUNT(e.department_id)
FROM departments d
JOIN employees e ON e.department_id = d.department_id
JOIN locations l USING (location_id)
GROUP BY d.department_name, l.city
ORDER BY d.department_name;
或在该单个值上使用一些聚合函数作为 MIN
或 MAX
。
SELECT d.department_name, MAX(l.city) AS city, COUNT(e.department_id)
FROM departments d
JOIN employees e ON e.department_id = d.department_id
JOIN locations l USING (location_id)
GROUP BY d.department_name
ORDER BY d.department_name;
不过,我更喜欢先聚合,然后再加入。您想加入部门及其员工人数,那么就这样做:
SELECT d.department_name, l.city, COALESCE(e.cnt, 0) AS employee_count
FROM departments d
JOIN locations l USING (location_id)
LEFT JOIN
(
SELECT department_id, COUNT(*) as cnt
FROM employees
GROUP BY department_id
) e ON e.department_id = d.department_id
ORDER BY d.department_name;
正如 Thorsten 出色地解释的那样,您还可以使用 OVER
和 PARTITION BY
函数对数据进行分组,这将消除对 GROUP BY
函数的使用。
SELECT d.department_name, l.city, COUNT(e.department_id) OVER (PARTITION BY e.department_id) as emp_count
FROM departments d
JOIN employees e ON e.department_id = d.department_id
JOIN locations l USING (location_id)
ORDER BY d.department_name;
我在 Oracle HR 模式中进行了查询以查看以下信息:
- 部门所在城市
- 部门员工总数
然而,查询无法正确执行并表示这“不是 GROUP BY 表达式”。
有谁知道问题出在哪里?提前致谢。
SELECT department_name, city, COUNT(employees.department_id)
FROM departments
JOIN employees on (departments.department_id=employees.department_id)
JOIN locations USING (location_id)
GROUP BY department_name;
问题是您同时拥有聚合列和 non-aggregated 列(在您的情况下 city
在 select 列表中。
因为我不知道位置 table 的结构并且考虑到 department
只有一个 location
定义你可以使用 max(city)
,
SELECT department_name, max(city) city, COUNT(employees.department_id) no_of_employees
FROM departments
JOIN employees on (departments.department_id=employees.department_id)
JOIN locations USING (location_id)
GROUP BY department_name;
您正在按部门分组并希望显示部门所在的城市。您希望这会起作用,因为每个部门都在一个城市。 (SQL 人们称之为函数依赖。)
要实现这一点,...
- 部门名称必须有唯一约束,否则您必须按 department_id 分组
- DBMS 必须检测并支持聚合查询中的函数依赖性
遗憾的是,Oracle 不支持聚合查询中的函数依赖。它迫使我们将每个这样的列放在 GROUP BY
子句或聚合函数中。
所以要么扩展 GROUP BY
子句:
SELECT d.department_name, l.city, COUNT(e.department_id)
FROM departments d
JOIN employees e ON e.department_id = d.department_id
JOIN locations l USING (location_id)
GROUP BY d.department_name, l.city
ORDER BY d.department_name;
或在该单个值上使用一些聚合函数作为 MIN
或 MAX
。
SELECT d.department_name, MAX(l.city) AS city, COUNT(e.department_id)
FROM departments d
JOIN employees e ON e.department_id = d.department_id
JOIN locations l USING (location_id)
GROUP BY d.department_name
ORDER BY d.department_name;
不过,我更喜欢先聚合,然后再加入。您想加入部门及其员工人数,那么就这样做:
SELECT d.department_name, l.city, COALESCE(e.cnt, 0) AS employee_count
FROM departments d
JOIN locations l USING (location_id)
LEFT JOIN
(
SELECT department_id, COUNT(*) as cnt
FROM employees
GROUP BY department_id
) e ON e.department_id = d.department_id
ORDER BY d.department_name;
正如 Thorsten 出色地解释的那样,您还可以使用 OVER
和 PARTITION BY
函数对数据进行分组,这将消除对 GROUP BY
函数的使用。
SELECT d.department_name, l.city, COUNT(e.department_id) OVER (PARTITION BY e.department_id) as emp_count
FROM departments d
JOIN employees e ON e.department_id = d.department_id
JOIN locations l USING (location_id)
ORDER BY d.department_name;