为什么我不能分组1当ORDER BY 1可以?

时间:2010-09-02 20:26:00

标签: sql

为什么列序号对ORDER BY合法,但对GROUP BY不合法?也就是说,任何人都可以告诉我为什么这个查询

SELECT OrgUnitID, COUNT(*) FROM Employee AS e GROUP BY OrgUnitID

不能写为

SELECT OrgUnitID, COUNT(*) FROM Employee AS e GROUP BY 1

编写像

这样的查询是完全合法的
SELECT OrgUnitID FROM Employee AS e ORDER BY 1

我真的想知道关系微积分是否存在一些微妙的东西,这会阻止分组正常工作。

问题是,我的例子非常简单。通常我想要分组的列实际上是一个计算,并且必须在GROUP BY中重复完全相同的计算是(a)烦人和(b)更有可能在维护期间产生错误。这是一个简单的例子:

SELECT DATEPART(YEAR,LastSeenOn), COUNT(*)
    FROM Employee AS e
    GROUP BY DATEPART(YEAR,LastSeenOn)

我认为SQL的规范化规则只能在数据库中表示一次 data ,也应该扩展到代码。我只想对该计算表达式进行一次修改(在SELECT列列表中),并且能够在GROUP BY中按顺序引用它。

澄清:我是专门研究SQL Server 2008的,但我想知道总体答案。

4 个答案:

答案 0 :(得分:8)

其中一个原因是因为ORDER BY是SQL Query中运行的最后一件事,这是操作的顺序

  1. FROM clause
  2. WHERE子句
  3. GROUP BY子句
  4. HAVING条款
  5. SELECT条款
  6. ORDER BY子句
  7. 因此,一旦获得SELECT子句中的列,就可以使用序数定位

    EDIT,根据评论补充说明 以此为例

    create table test (a int, b int)
    insert test values(1,2)
    go
    

    下面的查询将解析没有问题,它将无法运行

    select a as b, b as a
         from test
        order by 6
    

    这是错误

    Msg 108,Level 16,State 1,Line 3
    ORDER BY位置编号6超出了选择列表中项目数的范围。

    这也解析好

    select a as b, b as a
         from test
        group by 1
    

    但它出现了这个错误

    Msg 164,Level 15,State 1,Line 3
    每个GROUP BY表达式必须至少包含一个不是外部引用的列。

答案 1 :(得分:3)

SQL中存在许多基本的不一致性,使用标量就是其中之一。例如,任何人都可能期望


    select * from countries
    order by 1


    select * from countries
    order by 1.00001

是一个类似的查询(毕竟两者之间的差异可以无限小),但事实并非如此。

答案 2 :(得分:1)

使用别名:

SELECT DATEPART(YEAR,LastSeenOn) as 'seen_year', COUNT(*) as 'count'
    FROM Employee AS e
    GROUP BY 'seen_year'

** 编辑 **

如果您不允许GROUP BY alias,则此处为解决方案/解决方法:

SELECT seen_year
     , COUNT(*) AS Total 
  FROM (
    SELECT DATEPART(YEAR,LastSeenOn) as seen_year, *
    FROM Employee AS e
  ) AS inline_view
GROUP 
    BY seen_year

答案 3 :(得分:1)

我不确定标准是否指定它是否有效,但我认为它是依赖于实现的。我刚用一个SQL引擎尝试了你的第一个例子,它工作得很好。