如何比较SQL中的SUM和COUNT()?

时间:2014-07-02 13:18:56

标签: sql

我正在构建一个小查询来查找所有CustomerNumbers,其所有策略都处于特定状态(已终止)。

以下是我正在处理的查询

    select 
    a.cn
    ,p.pn
    , tp = COUNT(p.pn)
    , tp2 = SUM(case when p.status = 4 then 1 else 0 end)
from
(
        select cn, cn2
        from bc
        union 
        select cn, cn2= fn
        from ic
) as a
left join p as p
on a.cn = p.cn

group by 
    a.cn, 
    pn

我的问题是当我添加条款时:

   WHERE cn = tp

它表示列无效。我错过了一些非常明显的东西吗?

6 个答案:

答案 0 :(得分:3)

您不能在查询的同一级别使用别名。原因是where子句在select之前进行了逻辑评估,因此select中定义的别名在where中不可用

典型的解决方案是重复表达式(其他答案)或使用子查询或cte:

with cte as (
      <your query here>
     )
select cte.*
from cte
where TotalPolicies = TermedPolicies;

但是,在您的情况下,您有一个更简单的解决方案,因为您有一个聚合查询。所以只需使用:

having TotalPolicies = TermedPolicies

答案 1 :(得分:2)

您不能在where子句中使用别名聚合列名称。您必须使用表达式本身。此外,您不能将其用作cluase,而是在having子句中使用它

HAVING COUNT(p.PolicyNumber) = SUM(case when p.status = 4 then 1 else 0 end)

答案 2 :(得分:1)

您还可以将整个查询作为子查询,然后添加where语句:

select CustomerNumber
       ,PolicyNumber
       ,TotalPolicies
       ,TermedPolicies
  from (
    select 
        a.CustomerNumber
        ,p.PolicyNumber
        , TotalPolicies = COUNT(p.PolicyNumber)
        , TermedPolicies = SUM(case when p.status = 4 then 1 else 0 end)
    from
    (
            select CustomerNumber, CompanyName
            from BusinessClients 
            union 
            select CustomerNumber, CompanyName = FullName
            from IndividualClients
    ) as a
    left join Policies as p
    on a.CustomerNumber = p.CustomerNumber
    group by 
        a.CustomerNumber, 
        PolicyNumber
    ) tb
where TotalPolicies = TermedPolicies

答案 3 :(得分:0)

 select 
    a.CustomerNumber
    ,p.PolicyNumber
    , COUNT(p.PolicyNumber) as TotalPolicies 
    , SUM(case when p.status = 4 then 1 else 0 end) as TermedPolicies 
from
(
        select CustomerNumber, CompanyName
        from BusinessClients 
        union 
        select CustomerNumber, CompanyName = FullName
        from IndividualClients
) as a
left join Policies as p
on a.CustomerNumber = p.CustomerNumber
WHERE COUNT(p.PolicyNumber)= SUM(case when p.status = 4 then 1 else 0 end)
group by 
    a.CustomerNumber, 
    PolicyNumber

这应该有效。但它没有经过测试。

答案 4 :(得分:0)

要通过聚合函数进行筛选,必须将其包含在HAVING子句中,而不是WHERE子句中。

select 
    a.CustomerNumber
    ,p.PolicyNumber
    , TotalPolicies = COUNT(p.PolicyNumber)
    , TermedPolicies = SUM(case when p.status = 4 then 1 else 0 end)
from
(
        select CustomerNumber, CompanyName
        from BusinessClients 
        union 
        select CustomerNumber, CompanyName = FullName
        from IndividualClients
) as a
left join Policies as p
on a.CustomerNumber = p.CustomerNumber
having COUNT(p.PolicyNumber) = SUM(case when p.status = 4 then 1 else 0 end)
group by 
    a.CustomerNumber, 
    PolicyNumber

其原因与SQL引擎评估查询的方式有关。 WHERE子句的内容用于在应用聚合函数之前过滤掉行。如果你可以在那里引用聚合函数,引擎必须有一些方法来确定在聚合之前应用哪些谓词以及在之后应用哪些谓词。 HAVING子句允许引擎在两者之间有明确的界限:WHERE在聚合之前适用,HAVING在聚合之后适用。

答案 5 :(得分:0)

在处理具有分组的查询中的聚合时,您需要使用HAVING。这应该有效:

select 
a.CustomerNumber
,p.PolicyNumber
, TotalPolicies = COUNT(p.PolicyNumber)
, TermedPolicies = SUM(case when p.status = 4 then 1 else 0 end)
from
(
        select CustomerNumber, CompanyName
        from BusinessClients 
        union 
        select CustomerNumber, CompanyName = FullName
        from IndividualClients
) as a
left join Policies as p
on a.CustomerNumber = p.CustomerNumber

group by 
    a.CustomerNumber, 
    PolicyNumber
HAVING TermedPolicies = SUM(case when p.status = 4 then 1 else 0 end)