T-SQL GROUP BY:包含其他分组列的最佳方法

时间:2009-03-09 15:46:20

标签: sql-server tsql group-by aggregate

我是一位试图将某些东西移植到MS SQL Server的MySQL用户。

我正在加入几个表,并通过GROUP BY聚合一些列。

一个简单的例子是员工和项目:

select empID, fname, lname, title, dept, count(projectID)
from employees E left join projects P on E.empID = P.projLeader
group by empID

...这可以在MySQL中运行,但MS SQL更严格,要求所有内容都包含在聚合函数中,或者是GROUP BY子句的一部分。

因此,当然,在这个简单的例子中,我假设我可以在group by子句中包含额外的列。但我正在处理的实际查询非常复杂,并且包括在一些非聚合列上执行的一系列操作...即,尝试将所有这些操作包含在group by子句中会非常难看

那么有更好的方法吗?

6 个答案:

答案 0 :(得分:16)

你可以使用这些内容来解决这些问题:

select e.empID, fname, lname, title, dept, projectIDCount
from
(
   select empID, count(projectID) as projectIDCount
   from employees E left join projects P on E.empID = P.projLeader
   group by empID
) idList
inner join employees e on idList.empID = e.empID

这样您可以通过操作避免额外的组,并且您可以获得所需的任何数据。此外,您有更好的机会在某些情况下充分利用索引(如果您没有返回完整信息),并且可以更好地与分页相结合。

答案 1 :(得分:4)

“尝试将所有这些内容包含在group by子句中会非常难看。”

是的 - 这是唯一的方法* - 只需将非聚合列复制并粘贴到group by子句中,删除别名,这样就可以了......

*你可以将它包装在一个嵌套的SELECT中,但这可能就像丑陋......

答案 2 :(得分:2)

MySQL不常见 - 并且在技术上不符合SQL标准 - 允许您省略GROUP BY子句中的项目。在标准SQL中,select-list中的每个非聚合列必须在GROUP BY子句中完整列出(通过名称或序号,但不推荐使用)。

(哦,虽然MySQL很不寻常,但它允许速记很好。)

答案 3 :(得分:1)

您不需要加入子查询,因为没有必要根据员工的empID进行分组 - 您可以在项目的projectLeader字段中执行此操作。

通过内部联接(如我所说),您将获得至少拥有一个项目的员工列表。如果您想要所有员工的列表,只需将其更改为左连接

  select e.empID, e.fname, e.lname, e.title, e.dept, p.projectIDCount
    from employees e 
   inner join ( select projLeader, count(*) as projectIDCount
                  from projects
                 group by projLeader
              ) p on p.projLeader = e.empID

答案 4 :(得分:1)

我将假设empID是结果联接语句中的唯一ID。在这种情况下,您可以使用distinct获得相同的结果。

select distinct empID, fname, lname, title, dept, count(projectID)
from employees E
left join projects P on E.empID = P.projLeader

答案 5 :(得分:0)

select子句中的子查询也可能是合适的。它适用于给出的示例,但可能不适用于您正在处理的实际复杂查询。

select
        e.empID, fname, lname, title, dept
        , (select count(*) from projects p where p.projLeader = e.empId) as projectCount
from
   from employees E