计算SQL中的分组行数

时间:2013-02-21 21:08:58

标签: sql sql-server-2008 tsql count group-by

我有2个表,请求和响应

请求:

RequestId  UserId  InsertDate
1           1       5/4/2013
2           2       6/4/2012
.           .          .
.           .          .

对策:

Responseid  Requestid(FK)  ResponseCode  
    1           1              A   
    2           1              V
    3           1              M   
    4           2              A
    5           2              S   
    6           2              D
    .           .              .
    .           .              .

如果收到响应代码A和D,则请求被视为“已通过”(如我的示例中的id为2的请求)。我想编写一个返回3个东西的SQL查询:

  • “通过”请求的数量
  • 传递
  • 的请求的RequestID
  • 那些未通过的请求的RequestID

我写了一些东西,但我不喜欢它,我想有更好的方法。我的疑问是:

SELECT COUNT(*) 
FROM
(
  SELECT count(*) as c, req.RequestID
  FROM Responses res inner join Requests req 
  on req.RequestID = res.RequestID
  where 
      res.ResponseCode = 'A' or
      res.ResponseCode = 'D' 

  group by req.RequestID
)cc

where c = 2

提前致谢。

4 个答案:

答案 0 :(得分:2)

要返回包含响应代码A和D的请求ID,一种方法是使用HAVINGCOUNT

SELECT res.requestId
FROM Responses res inner join Requests req 
  on req.RequestID = res.requestid
WHERE res.ResponseCode IN ('A','D')
GROUP BY res.requestId
HAVING COUNT(DISTINCT res.ResponseCode) = 2

SQL Fiddle Demo

答案 1 :(得分:1)

我无法想到另一种根本不同的方式(即没有相同的子查询或CTE)。但是,我会分别测试“A”和“D”值:

SELECT COUNT(*) as c, req.RequestID
FROM Responses res inner join
     Requests req 
     on req.RequestID = res.EquifaxIDCompareRequestID
where res.ResponseCode in ('A', 'D')
group by EquifaxIDCompareRequestID
having SUM(case when res.ResponseCode = 'D' then 1 else 0 end) > 0 and
       SUM(case when res.ResponseCode = 'A' then 1 else 0 end)

having子句类似于外部where子句,除了检查“A”和“D”都在结果集中。

使用连接或子查询还有另一种方法。像这样:

select EquifaxIDCompareRequestID
from Requests req
where EquifaxIDCompareRequestID in (select RequestID from responses where ResponseCode = 'A') and
      EquifaxIDCompareRequestID in (select RequestID from responses where ResponseCode = 'D') 

答案 2 :(得分:1)

SELECT r1.RequestID
FROM Responses R1
JOIN Responses R2
  on R2.RequestID = R1.RequestID
 and R1.ResponseCode = 'A' 
 and R2.ResponseCode = 'D'
compute count(r1.RequestID)

(计算语法不正确)

不通过

SELECT distinct (r1.RequestID)
FROM Responses R1
FULL OUTTER JOIN Responses R2
  on R2.RequestID = R1.RequestID
 and R1.ResponseCode = 'A' 
 and R2.ResponseCode = 'D'
WHERE R2.RequestID is null 
   OR R1.RequestID is null

SELECT r1.RequestID
FROM  Responses R1
WHERE R1.ResponseCode = 'A' 
INTERSECT 
SELECT r1.RequestID
FROM  Responses R1
WHERE R1.ResponseCode = 'D'

不通过

SELECT r1.RequestID
FROM  Responses R1
EXCEPT
SELECT r1.RequestID
FROM  Responses R1
WHERE R1.ResponseCode = 'D'
   OR R1.ResponseCode = 'A' 

答案 3 :(得分:1)

对于每个requestId,下面给出了它是否通过以及它所在的组中的总数(通过或失败)(即,如果它通过,则通过的请求总数;如果失败,失败的请求总数。

with myCTE as
(
    select rq.requestId, case when rA.responseCode='A' and rD.responseCode='D' then 1 else 0 end as passed
    from dbo.Requests as rq
    outer apply
    (
        select top (1) re.responseCode
        from dbo.Responses as re
        where re.requestId=rq.requestId
            and re.responseCode='A'
    ) as rA
    outer apply
    (
        select top (1) re.responseCode
        from dbo.Responses as re
        where re.requestId=rq.requestId
            and re.responseCode='D'
    ) as rD
)
select *, count(*) over (partition by m.passed) as totalNumInGroup
from myCTE as m