子查询中的SQL Group By语句

时间:2014-02-20 17:36:14

标签: sql sql-server group-by subquery

我正在尝试编写一个查询,该查询将返回每个员工每月发出的“主动调用案例”的数量以及所有案例的总数。基本上,我希望返回3列;一个EmployeeName,该月的主动呼叫计数,以及该月的总呼叫计数。为了尝试实现这一点,我使用了一个子查询。以下是我到目前为止的情况:

Select OpenedByName AS EmployeeName, Count(OpenedByName) As NumberOfProactiveCallsMONTH,
  (Select Count(OpenedByName)
   From table1
   Where OpenDate Between '2/1/2014' and '3/1/2014' Group By OpenedByName) AS
   TotalTicketsMONTH
From table1
Where OpenDate Between '2/1/2014' and '3/1/2014' AND ProblemType = 17 
Group By OpenedByName

运行查询后,我得到错误说:

"Msg 512, Level 16, State 1, Procedure SalesMTDSubQuery, Line 7 Subquery returned
more than 1 value. This is not permitted when the subquery follows =, !=, <, <= ,
>, >= or when the subquery is used as an expression."

我认为由于我在子查询中添加的GroupBy语句而返回此错误。当我删除GroupBy时,它将为每个员工返回相同的值。我是使用SQL的新手,所以我不太确定这方面的好方法。任何帮助将不胜感激。

谢谢!

4 个答案:

答案 0 :(得分:1)

这样的东西
SELECT  OpenedByName AS EmployeeName,
        SUM(CASE WHEN ProblemType = 17 THEN 1 ELSE 0 END) AS NumberOfProactiveCallsMONTH,
        COUNT(1) TotalTicketsMONTH
FROM Table1
Where OpenDate Between '2/1/2014' and '3/1/2014' 
GROUP BY OpenedByName

您收到的错误是由于当使用子查询作为列时,它不能返回超过1的值。

现在你的结构方式,它会返回每个OpenedByName的所有COUNT值,而不是每个OpenedBy的单个值。

如果您真的希望使用您的查询,则需要将列中的查找限制为实际的OpenedByName。像

这样的东西
Select OpenedByName AS EmployeeName, Count(OpenedByName) As NumberOfProactiveCallsMONTH,
  (Select Count(OpenedByName)
   From table1 t
   Where OpenDate Between '2/1/2014' and '3/1/2014' 
   AND t.OpenedByName = t1.OpenedByName) AS
   TotalTicketsMONTH
From table1 t1
Where OpenDate Between '2/1/2014' and '3/1/2014' AND ProblemType = 17 
Group By OpenedByName

答案 1 :(得分:0)

您需要将子选择与外部语句相关联,否则,正如您所注意到的,您在子选择中返回多行不起作用。

SELECT  OpenedByName AS EmployeeName
      , COUNT(OpenedByName) AS NumberOfProactiveCallsMONTH
      , ( SELECT    COUNT(OpenedByName)
          FROM      table1 b
          WHERE     OpenDate BETWEEN '2/1/2014' AND '3/1/2014'
                AND b.OpenedByName = a.OpenedByName
          GROUP BY  OpenedByName
        ) AS TotalTicketsMONTH
FROM    table1 a
WHERE   OpenDate BETWEEN '2/1/2014' AND '3/1/2014'
        AND ProblemType = 17
GROUP BY OpenedByName

但是你可以通过使用条件和而不是子选择来大大简化:

SELECT  OpenedByName AS EmployeeName
      , SUM(ProblemType = 17) NumberOfProactiveCallsMONTH
      , COUNT(OpenedByName) AS TotalTicketsMONTH
FROM    table1
WHERE   OpenDate BETWEEN '2/1/2014' AND '3/1/2014'
GROUP BY OpenedByName

答案 2 :(得分:0)

你可以这样使用

Select a.OpenedByName AS EmployeeName, Count(a.OpenedByName) As NumberOfProactiveCallsMONTH,
b.TotalTicketsMONTH  AS   TotalTicketsMONTH
From table1 a
INNER JOIN   
  (Select OpenedByName ,Count(OpenedByName) AS TotalTicketsMONTH   From table1
  Where OpenDate Between '2/1/2014' and '3/1/2014' Group By OpenedByName) b ON
  a.OpenedByName =  b.OpenedByName
Where a.OpenDate Between '2/1/2014' and '3/1/2014' AND a.ProblemType = 17 
Group By a.OpenedByName

答案 3 :(得分:0)

您需要将内部查询与外部查询建立关系:

SELECT  t1.OpenedByName AS EmployeeName, 
        COUNT(t1.OpenedByName) As NumberOfProactiveCallsMONTH,
        (   SELECT  COUNT(OpenedByName)
            FROM    table1 t2
            WHERE   t2.OpenDate BETWEEN '2/1/2014' AND '3/1/2014'
            AND     t1.OpenedByName = t2.OpenedByName
        ) AS TotalTicketsMONTH
FROM    table1 t1
WHERE   t1.OpenDate BETWEEN '2/1/2014' AND '3/1/2014' 
AND     t1.ProblemType = 17 
GROUP BY t1.OpenedByName;

但是,您可以使用条件聚合来简化查询(即仅在满足其他条件时进行计数):

SELECT  t1.OpenedByName AS EmployeeName,
        COUNT(CASE WHEN t1.ProblemType = 17 THEN t1.OpenedByName END) As NumberOfProactiveCallsMONTH,
        COUNT(t1.OpenedByName) As TotalTicketsMONTH
FROM    table1 t1
WHERE   t1.OpenDate BETWEEN '2/1/2014' AND '3/1/2014' 
GROUP BY t1.OpenedByName;

下一个改进是将日期格式更改为非特定文化格式 - {1} 2月1日或2月1日?如果您使用2/1/2014,则不存在歧义。

最后,您的查询将包括3月1日午夜开放的门票,我怀疑这些门票不应包含在2月的数据中,您最好使用yyyyMMdd和`&lt;'。进行最终查询:

>=

有关日期范围查询的进一步阅读: