TSQL:外连接表的计数产生不正确的结果

时间:2015-02-03 02:36:02

标签: sql-server-2008 tsql count outer-join

生成有关SQL Server 2008的报告。我使用LEFT OUTER JOIN加入了一个表和另外五个表。当我对其他表运行计数时,我得到的数据不正确。我知道为什么,但我不确定如何解决它。

该查询正在跟踪学校的招生候选人。当他们完成整个过程时,他们会在流程的每个主要阶段被标记。我需要的是计算在特定时期(年和月)中通过特定阶段的数量。大部分都有效。但是,如果候选人在此期间通过任何阶段,该候选人也会在之前阶段“计算”,即使他们在查询期之前发生。一个很好的例子是AD_35,其中应该有一个人用于特定的学术课程,但输出结果为2.当我仅查询AD_35表时,我得到正确的信息。所以我知道问题在于外连接,但我不确定如何克服这个问题(在子查询中尝试了各种标准,生成我的命名输出)。应该是一个容易的人...提前谢谢,代码如下。 :年份和:月份用于用户输入,并将填充数值(例如2015 1)

CW

SELECT DISTINCT 
   ad_candidacy.prog_cde,   
   ad_candidacy.stageyr,   
   ad_candidacy.stagemo,   
   Count (case when (ad_02.stageyr in (:Year, :Year -1, :Year-2) and ad_02.stagemo <= :month) then 1 else null end) as Inquiry,   
   Count (case when (ad_05.stageyr in (:Year, :Year -1, :Year-2) and ad_05.stagemo <= :month) then 1 else null end) as Applied,   
   Count (case when (ad_35.stageyr in (:Year, :Year -1, :Year-2) and ad_35.stagemo <= :month and ad_35.id_num = ad_candidacy.id_num and ad_35.stageyr = ad_candidacy.stageyr and ad_35.stagemo=ad_candidacy.stagemo) then 1 else null end) as Accepted,   
   Count (case when (ad_50.stageyr in (:Year, :Year -1, :Year-2) and ad_50.stagemo <= :month) then 1 else null end) as Matriculated,   
   Count (case when (ad_enroll.stageyr in (:Year, :Year -1, :Year-2) and ad_enroll.stagemo <= :month) then 1 else null end) as Enrolled,   
   ad_candidacy.stagemo_long  
FROM 
   ad_candidacy 
LEFT OUTER JOIN 
   ad_02 ON ad_candidacy.id_num = ad_02.id_num 
LEFT OUTER JOIN 
   ad_05 ON ad_candidacy.id_num = ad_05.id_num 
LEFT OUTER JOIN 
   ad_35 ON ad_candidacy.id_num = ad_35.id_num 
LEFT OUTER JOIN 
   ad_enroll ON ad_candidacy.id_num = ad_enroll.id_num 
LEFT OUTER JOIN 
   ad_50 ON ad_candidacy.id_num = ad_50.id_num  
WHERE 
   (ad_candidacy.stageyr in (:Year, :Year -1, :Year-2) ) 
   AND ( ad_candidacy.stagemo <= :Month )   
GROUP BY 
   ad_candidacy.prog_cde,   
   ad_candidacy.stageyr,   
   ad_candidacy.stagemo,   
   ad_candidacy.stagemo_long  
ORDER BY 
   ad_candidacy.stageyr ASC  

2 个答案:

答案 0 :(得分:0)

加入多个表需要考虑连接条件。第二个表可能有多行用于同一行。为了确保您最终得到重复项,您可以在加入第一个表之前在子查询中搜索第二个表。

SELECT a.Name, 
       b.Total
FROM table1 as a
LEFT OUTER JOIN ( SELECT table1Id, Total = COUNT(b.some_measure) from table2 group by table1Id)as b ON a.table1Id = b.table1Id

答案 1 :(得分:0)

Ako的回答指出了我正确的方向。我正在使用子查询,但他的例子导致了正确的输出。以下是代码的工作版本。谢谢!

SELECT DISTINCT 
   ad_candidacy.prog_cde,   
   ad_candidacy.stageyr,   
   ad_candidacy.stagemo, 
   ad_candidacy.StageMo_Long,
   COUNT (case when (Inquiry IS NOT NULL) then 1 else null end) as Inquiry,
   COUNT (case when (Applied IS NOT NULL) then 1 else null end) as Applied,
   count (case when (Accepted is not null) then 1 else null end) as Accepted,
   COUNT (case when (Matriculated IS NOT NULL) then 1 else null end) as Matriculated,
   count (case when (Enrolled is not null) then 1 else null end) as Enrolled
FROM 
   ad_candidacy
LEFT OUTER JOIN
 (select id_num, Inquiry = COUNT (id_num) from ad_02 where stageyr in (:year, :year-1, :year-2) and StageMo <= :month group by id_num) as ad_02 on ad_candidacy.id_num = ad_02.id_num     
LEFT OUTER JOIN
 (select id_num, Accepted = COUNT (id_num) from ad_35 where stageyr in (:year, :year-1, :year-2) and StageMo <= :month group by id_num) as ad_35 on ad_candidacy.id_num = ad_35.id_num    
LEFT OUTER JOIN
 (select id_num, Applied = COUNT (id_num) from ad_05 where stageyr in (:year, :year-1, :year-2) and StageMo <= :month group by id_num) as ad_05 on ad_candidacy.id_num = ad_05.id_num    
LEFT OUTER JOIN
 (select id_num, Matriculated = COUNT (id_num) from ad_50 where stageyr in (:year, :year-1, :year-2) and StageMo <= :month group by id_num) as ad_50 on ad_candidacy.id_num = ad_50.id_num   
LEFT OUTER JOIN
 (select id_num, Enrolled = COUNT (id_num) from ad_enroll where stageyr in (:year, :year-1, :year-2) and StageMo <= :month group by id_num) as ad_enroll on ad_candidacy.id_num = ad_enroll.id_num  
WHERE 
   (ad_candidacy.stageyr in (:year, :year-1, :year-2) ) 
   AND ( ad_candidacy.stagemo <= :month )   
GROUP BY 
   ad_candidacy.prog_cde,   
   ad_candidacy.stageyr,   
   ad_candidacy.stagemo,   
   ad_candidacy.stagemo_long