2016-03-04 72 views
1

这是我的查询:在GROUP使用SELECT'd Case语句的COLUMNNAME BY

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语句声明?

所以基本上,为什么做我的代码工作时GROUP BY前评估SELECT?

+0

我的SQL [扩展了'GROUP BY'子句](http://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html)在一个方式的数量,这是其中之一(在页面的底部链接)。我不知道MySQL查询编译的内部工作原理,所以虽然你所说的操作顺序是正确的,(虽然缺少'HAVING'),但我无法准确解释扩展工作的原因。 – GarethD

+0

使用的标记dbms。涉及到GROUP BY时,MySQL和Postgresql有很大不同。 – jarlh

+0

一般提示(独立于dbms):'GROUP BY d.DeptName,e.WorkCity'。 – jarlh

回答

0

您描述的处理常常用于解释查询的编译以及何时已知什么标识符。 SQL Server对此非常明确,其规则记录在here

只是因为SQL Server这样做,并不意味着所有的数据库都这样做。

因此,不同的数据库在允许各个子句中的列别名时更好或更差。 MySQL和Postgres允许GROUP BYHAVING子句中的列别名; Oracle和SQL Server不这样做。所有数据库都允许ORDER BY中的列别名。实际上,一些(如Hive)需要列别名并且不允许聚合函数。

我相信ANSI标准有话要说这个话题。它是否真正明确是另一个问题,但不同的数据库有不同的个性。

而且,本讨论涉及查询的分析的词汇。实际执行顺序与原始声明无关。大多数数据库引擎使用数据流引擎,数据流操作符和SQL构造之间不存在一对一的对应关系。

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语法。更容易编写(没有错误),更易于阅读和维护,并且如果需要,也更容易转换为外连接!

+0

我的问题更多地沿着**的原因**当GROUP BY在SELECT之前求值时,我的代码是否工作? – Silent

+0

根据ANSI SQL标准,您的查询不应起作用。我猜Postgresql的开发人员有太多的人要求这个有点奇怪的扩展 - 调整到一个非常普通的初学者的编程错误......(其他几个dbms产品也有这个扩展。) – jarlh

1

答案是Postgresql中的名称解析允许这样做。

从Postgresql 9.3文档(第7.2.3节。在GROUP BY和HAVING子句):

在严格的SQL,GROUP BY只能由源表 但PostgreSQL的扩展这也让GROUP BY到组通过在选择列表列 列组。也可以使用值表达式而不是简单的 列名进行分组。

Link