对SQL语法感到好奇。所以,如果我有
SELECT
itemName as ItemName,
substring(itemName, 1,1) as FirstLetter,
Count(itemName)
FROM table1
GROUP BY itemName, FirstLetter
这是不正确的,因为
GROUP BY itemName, FirstLetter
真的应该
GROUP BY itemName, substring(itemName, 1,1)
但为什么我们不能简单地使用前者来方便呢?
答案 0 :(得分:245)
实现SQL就好像按以下顺序执行查询一样:
对于大多数关系数据库系统,此顺序说明了哪些名称(列或别名)有效,因为它们必须在上一步中引入。
因此,在Oracle和SQL Server中,您不能在SELECT子句中定义的GROUP BY子句中使用术语,因为GROUP BY在SELECT子句之前执行。
但也有例外:MySQL和Postgres似乎有额外的智能,允许它。
答案 1 :(得分:25)
您可以随时使用子查询,以便可以使用别名;当然,检查性能(可能数据库服务器将运行相同,但永远不会伤害验证):
SELECT ItemName, FirstLetter, COUNT(ItemName)
FROM (
SELECT ItemName, SUBSTRING(ItemName, 1, 1) AS FirstLetter
FROM table1
) ItemNames
GROUP BY ItemName, FirstLetter
答案 2 :(得分:15)
至少在PostgreSQL中,您可以在GROUP BY子句的结果集中使用列号:
SELECT
itemName as ItemName,
substring(itemName, 1,1) as FirstLetter,
Count(itemName)
FROM table1
GROUP BY 1, 2
当然,如果您以交互方式执行此操作并且编辑查询以更改结果中列的数量或顺序,那么这将开始变得很痛苦。但仍然。
答案 3 :(得分:12)
由于处理的逻辑顺序,SQL Server不允许您引用GROUP BY子句中的别名。 GROUP BY子句在SELECT子句之前处理,因此在评估GROUP BY子句时不知道别名。这也解释了为什么可以在ORDER BY子句中使用别名。
以下是有关SQL Server logical processing phases的信息的一个来源。
答案 4 :(得分:4)
请注意,在Group By中使用别名(对于支持它的服务,例如postgres)可能会产生意外结果。例如,如果您创建内部语句中已存在的别名,则“分组依据”将选择内部字段名称。
<<entry>>
答案 5 :(得分:4)
我没有回答为什么会这样,但只是想通过使用CROSS APPLY
来创建别名来展示SQL Server中的限制。然后在GROUP BY
子句中使用它,如下所示:
SELECT
itemName as ItemName,
FirstLetter,
Count(itemName)
FROM table1
CROSS APPLY (SELECT substring(itemName, 1,1) as FirstLetter) Alias
GROUP BY itemName, FirstLetter
答案 6 :(得分:3)
有些DBMS会让您使用别名而不必重复整个表达式 Teradata就是这样一个例子。
我根据Bill this SO question中记录的原因避免使用Bill建议的序号位置表示法。
简单而强大的替代方法是始终在GROUP BY子句中重复表达式 DRY不适用于SQL。
答案 7 :(得分:1)
在对SQLite中的视图中的结果进行分组时,请注意使用别名。如果别名与任何基础表的列名相同(对于视图),您将得到意外结果。
答案 8 :(得分:0)
当天我发现现在支持Oracle的前DEC产品Rdb允许在GROUP BY中使用列别名。主流Oracle到版本11不允许在GROUP BY中使用列别名。不确定Postgresql,SQL Server,MySQL等将允许或不允许。 YMMV。
答案 9 :(得分:0)
至少在Postgres中,您可以在group by子句中使用别名:
选择 itemName作为ItemName1, substring(itemName,1,1)作为FirstLetter, Count(itemName) 从表1 GROUP BY ItemName1,FirstLetter;
我不建议将别名重命名为大写形式,这会引起混淆。