如何计算并显示一行在多个连接表中出现的次数?

时间:2014-07-08 18:51:28

标签: sql sql-server-2008

我写了下面的查询,它显示了与两个特定的ables相关的ApplicationID。我需要结果返回每个Applications.AppID出现在具有应用程序名称的行旁边的那些表中的次数。我使用了不同的,因为在我的结果中我只希望名称出现一次,但旁边有一个数字表示它被使用了多少次。以下示例。我以前写了计数条件,但只针对单个表。

  SELECT 0 AppId   ,
         'Select an Application' ApplicationName
union all
  select .1        ,
         '--All--'
union all
  SELECT DISTINCT
         Applications.AppId ,
         Applications.ApplicationName
  FROM ImpactedApplications ,
       SupportingApplications 
  JOIN applications              ON SupportingApplications.Appid = applications.appid
  JOIN ImpactedApplications Apps on SupportingApplications.AppId = Applications.AppId

返回如下内容:

0.0   Select an Application
0.1   --All--
12.0  APP A
59.0  APP B
60.0  APP C
71.0  APP D
74.0  APP E
121.0 APP F
124.0 APP G
130.0 APP H

我希望它返回这样的内容:

0.0   Select an Application
0.1   --All--
12.0  APP A 1
59.0  APP B 2
60.0  APP C 1
71.0  APP D 4
74.0  APP E 3
121.0 APP F 1
124.0 APP G 2
130.0 APP H 2

感谢您的任何帮助。

从帮助查询中添加结果

12 APP A 17161
59 APP B 51483
60 APP C 85805
71 APP D 17161

3 个答案:

答案 0 :(得分:1)

DISTINCT在逻辑上等同于GROUP BY:

SELECT Applications.AppId, Applications.ApplicationName
   ,COUNT(*)
FROM SupportingApplications 
INNER JOIN    applications ON SupportingApplications.Appid = applications.appid
INNER JOIN ImpactedApplications as Apps on SupportingApplications.AppId = Applications.AppId 
GROUP BY Applications.AppId, Applications.ApplicationName

答案 1 :(得分:0)

SELECT 0 AppId, 'Select an Application' ApplicationName union all
                                select .1,'--All--' union all
SELECT DISTINCT app.AppId, app.ApplicationName,count(app.AppId)
FROM  SupportingApplications sa 
INNER JOIN    applications app ON sa.Appid = applications.appid
--INNER JOIN ImpactedApplications as Apps on sa.AppId = app.AppId
group by app.AppId, app.ApplicationName

看起来你没有使用ImpactedApplications表做任何事情,所以idk可能会删除该行

答案 2 :(得分:0)

首先,您确实知道订单是未指定,除非您使用order by订购结果集?这意味着无法保证union all中的前两个选项将首先出现。

所以,让我们把这两个去掉,因为它们实际上与实际问题无关。让我们考虑核心select

选择不同          Applications.AppId,          Applications.ApplicationName   来自ImpactedApplications,        SupportingApplications   JOIN应用程序ON SupportingApplications.Appid = applications.appid   在SupportingApplications.AppId = Applications.AppId

上加入ImpactedApplications应用程序

并剖析它。

问题#1。
select distinct通常是代码气味,表示您没有正确的加入条件,或者您没有正确理解所涉及关系的基数。

问题#2。确实,情况确实如此。您正在将旧学校,ISO / ANSI之前的连接与ISO / ANSI连接混合使用。由于FROM子句中的前两个表是以ISO / ANSI之前的样式连接的,并且没有where子句带有加入它们的条件,因此上述select语句与

完全相同

选择不同          a.AppId,          a.ApplicationName   来自ImpactedApplications ia   cross join支持应用程序sa   在sa.Appid = a.appid上加入应用程序a   在sa.AppId = a.AppId

上加入ImpactedApplications应用程序

我很确定你不打算生成2个表的笛卡尔积。你没有描述表模式,但我怀疑你的问题陈述

  

我需要结果返回每个Applications.AppID的次数   出现在具有应用程序名称的行旁边的那些表中。

你想要更多的东西:

select AppId           = a.AppId           ,
       AppName         = a.ApplicationName ,
       ImpactedCount   = coalesce( ia.Cnt , 0 ) ,
       SupportingCount = coalesce( sa.Cnt , 0 ) ,
       Total           = coalesce( ia.Cnt , 0 )
                       + coalesce( sa.Cnt , 0 )
from      Applications           a
left join ( select AppId = t.AppId ,
                   Cnt   = count(*)
            from ImpactedApplications t
            group by t.AppId
          ) ia on ia.AppId = a.AppId
left join ( select AppId = t.AppId ,
                   Cnt   = count(*)
            from SupportingApplications t
            group by t.AppId
          ) sa on sa.AppId = a.AppId

如果要将结果限制为具有非零值的行,可以将left join子句更改为join,但这意味着您只能获得具有非零值的那些行两者都是非零值。而是添加一个where子句来限制结果集:

where sa.Cnt > 0
   OR ia.Cnt > 0

除了过滤掉两个计数均为零的任何行之外,它还会删除两行都有null计数的行,表示left join中没有匹配。