这是我的疑问:
SELECT d.DeptName, CASE WHEN e.WorkCity is NULL THEN 'Mobile'
ELSE 'Stationary'
END AS EmpType,
AVG(e.MonthlyPayScale) AS AvgMnthPay
FROM Department d, Employee e
WHERE d.DeptId = e.DeptId
GROUP BY d.DeptName, EmpType
ORDER BY d.DeptName, EmpType
这是我的输出似乎是正确的:
deptname | emptype | avgmnthpay
----------+------------+------------------------
EvanDept | Mobile | 7500.0000000000000000
MaxDept | Stationary | 11250.0000000000000000
PaulDept | Mobile | 5000.0000000000000000
PaulDept | Stationary | 12500.0000000000000000
(4 rows)
按部门名称和移动/固定员工分组,计算每个组员工的平均月工资。
据我所知,这是SQL查询的排序:
FROM
WHERE
GROUP BY
SELECT
ORDER BY
因此GROUP BY语句在SELECT语句之前发生 。那么为什么:
GROUP BY d.DeptName, EmpType
了解有关EmpType的任何信息,这是在SELECT语句中的CASE语句中声明的吗?
基本上,为什么在SELECT之前评估GROUP BY时我的代码是否有效?
答案 0 :(得分:1)
在派生表中执行CASE
表达式:
select DeptName, EmpType, AVG(MonthlyPayScale) AS AvgMnthPay
FROM
(
SELECT d.DeptName as DeptName,
CASE WHEN e.WorkCity is NULL THEN 'Mobile'
ELSE 'Stationary'
END AS EmpType,
e.MonthlyPayScale as MonthlyPayScale
FROM Department d
JOIN Employee e ON d.DeptId = e.DeptId
)
GROUP BY DeptName, EmpType
ORDER BY DeptName, EmpType
还切换到现代的,明确的JOIN
语法。更容易编写(没有错误),更易于阅读和维护,并且如果需要也更容易转换为外部联接!
答案 1 :(得分:1)
答案是Postgresql中的名称解析允许这样做。
从Postgresql 9.3的文档(第7.2.3节.GROUP BY和HAVING子句):
在严格的SQL中,GROUP BY只能按源表的列进行分组 但PostgreSQL对此进行了扩展,以允许GROUP BY按列分组 在选择列表中。按值表达式分组而不是简单 列名也是允许的。
答案 2 :(得分:0)
您描述的处理通常用于解释查询的编译以及何时知道哪些标识符。 SQL Server对此非常明确,并且他们的规则记录在here。
仅仅因为SQL Server以这种方式执行,并不意味着所有数据库都是这样做的。
因此,不同的数据库在允许各个子句中的列别名方面更好或更差。 MySQL和Postgres允许GROUP BY
和HAVING
子句中的列别名; Oracle和SQL Server没有。所有数据库都允许ORDER BY
中的列别名。实际上,有些内容(例如Hive)需要列别名,并且不允许聚合函数。
我确信ANSI标准对此主题有话要说。它是否真的是明确的是另一个问题,但不同的数据库有不同的个性。
并且,此讨论涉及查询的词汇分析。实际执行顺序与原始语句无关。大多数数据库引擎使用数据流引擎,数据流运算符和SQL结构之间没有一对一的对应关系。