【问题标题】:Calculate number of grouped rows in SQL计算SQL中分组的行数
【发布时间】:2013-02-21 21:08:58
【问题描述】:

我有 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 的请求)。我想写一个 sql 查询,它会返回 3 件事:

  • “通过”请求的数量
  • 通过的请求的请求 ID
  • 未通过的请求的 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

提前致谢。

【问题讨论】:

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


    【解决方案1】:

    要返回同时具有响应代码 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

    【讨论】:

      【解决方案2】:

      通过

      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】:

        我想不出另一种完全不同的方法(即没有等效的子查询或 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') 
        

        【讨论】:

          【解决方案4】:

          对于每个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
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2019-11-28
            • 1970-01-01
            • 2012-12-31
            • 2021-10-18
            • 2014-07-12
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多