使用子查询进行分组

时间:2017-09-27 21:34:16

标签: sql sql-server

我知道我们不能在group by子句中使用子查询。试图了解它是如何工作的。

如果有2个表dept和dept_code,我正在查看dept代码的工资总和。

假设我选择使用子查询而不是连接。

    create table #dept (id int,name varchar(10),salary int)
    create table #dept_codes (id int,name varchar(10),code varchar(10))

    insert into #dept values (1,'HR',100)
    insert into #dept values (2,'IT',500)
    insert into #dept values (3,'HR',1500)
    insert into #dept values (4,'HR',200)
    insert into #dept values (5,'MAR',1200)

    insert into #dept_codes values (1,'HR','XX')
    insert into #dept_codes values (2,'IT','XXY')
    insert into #dept_codes values (3,'MAR','XXYZ')

我要提出的问题是:

     select (select code from #dept_Codes b where b.name = a.name) as code
         ,sum(salary) as salary
     from #dept a
     group by a.name

输出是:

     code salary
     XX     1800
     XXY     500
     XXYZ    1200

我试图了解这是如何工作的。如果我在子查询中有2个连接条件,我是否在group by子句中给出两个列?

对于在select中使用子查询的所有情况,查询是否为真?

3 个答案:

答案 0 :(得分:0)

您必须在group by中指定两列,是的。您在外部表格中引用的所有列(示例中为#dept a)必须是sum()之类的聚合函数,或者包含在group by中。

这也扩展到相关子查询中外表的列。如果您要将and a.id = b.id添加到子查询中,则会抛出错误

Msg 8120, Level 16, State 1, Line 19 Column '#dept.id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

答案 1 :(得分:0)

是的,正如Xedni指出你需要GROUP BY中的两个列。我建议使用JOIN,只是为了便于阅读。

 SELECT a.name,code,SUM(salary) AS salary
 FROM #dept a
 INNER JOIN #dept_codes b ON a.name=b.name
 GROUP BY a.name,code

或者,如果您不想在结果中使用名称(您仍然需要GROUP BY中的两个列):

 SELECT code,SUM(salary) AS salary
 FROM #dept a
 INNER JOIN #dept_codes b ON a.name=b.name
 GROUP BY a.name,code

答案 2 :(得分:0)

当您应用“分组依据”时,您不必选择“分组依据”中的列。 因此,您可以轻松编写。

 select sum(salary) as salary
 from #dept a
 group by a.name

并得到了

 salary 
 1800   
 500    
 1200   

现在您可以添加子查询

select (select TOP(1) code from #dept_Codes b ) AS Code
,sum(salary) as salary
from #dept a
group by a.name
code    salary
XX  1800
XX  500
XX  1200

此时,我们的子查询的值不以任何方式绑定到该行。所以它可能总会给你相同的价值(不保证)。

从这一点开始,您可以根据名称链接表格并获取查询。

select (select TOP(1) code from #dept_Codes b where b.name = a.name ) AS Code
,sum(salary) as salary
from #dept a
group by a.name

注意TOP(1)是重要的。

那么你必须在“group by”中添加第二列吗?也许

你可以在下面的语句中运行它会运行得很好,但是如果你想通过聚合函数得到a.id的实际值而不是值,它将需要成为group by的一部分。

select (select TOP(1) code from #dept_Codes b where b.name = a.name and b.id = MIN(a.id) ) AS Code
,sum(salary) as salary
from #dept a
group by a.name
Code    salary
XX  1800
XXY 500
NULL    1200

至于你的第二个问题。如果查看上表,可以看到最后一个代码为NULL。子查询被评估为空,所以我们得到了一个N​​ULL。 这是因为代码MAR在dept表中的id只有5,MIN(a.id)将是3。