Sql加入返回Null结果

时间:2018-01-08 06:33:07

标签: sql sql-server

我有4个表,我试图从中获取数据,但我的join语句返回null。我尝试了完整的,左右连接但没有成功。 Blow我提供了我的代码和图表,返回null值的表是ChannelData表。我试图从这张表中加总Vvalue:

DECLARE @bp varchar(4)
DECLARE @priority varchar(2)
DECLARE @startDate datetime
DECLARE @endDate datetime

SET @bp = 1710
SET @priority = 2

SET @endDate = (SELECT EndDate FROM BillingPeriod WHERE BillingPeriodClass_ID = 1 AND CODE = @BP)
SET @startDate = (SELECT EndDate FROM BillingPeriod WHERE BillingPeriodClass_ID = 1 AND CODE = @BP -1 )
SET @startDate = dateadd(minute, 1, @startDate)


SELECT  CGS.Description,
        CD.VValue, DI.Margin, @priority AS PRIORITY

FROM DataIntegrity AS DI

FULL JOIN CGS AS CGS ON CGS.ID = DI.CGS_ID_1 OR CGS.ID = DI.CGS_ID_2 
LEFT JOIN ChannelParameter AS CP ON CP.ID = CGS.ID
LEFT JOIN ChannelData AS CD ON CP.ID = CD.ID AND DI.CGS_ID_1 = CD.ID AND DI.CGS_ID_2 = CD.ID

where DI.Priority = @priority

 group by CGS.Description, CD.VValue,  DI.Margin

结果

enter image description here

db_diagram

enter image description here

另一个例子,我在尝试此查询时,在包含Report表而不是DI表时获取空值:

second result set

SELECT SUM(CD.VValue),  CGS.Description,
SUM(CD.VValue)

FROM CGS AS CGS

FULL JOIN ChannelParameter AS CP ON CP.ID = CGS.ID
FULL JOIN ChannelData AS CD ON CP.ID = CD.ID
FULL JOIN Report AS R on R.CGS_ID = CGS.ID

where -- CD.DDate BETWEEN @startDate AND @endDate 
             r.Description = 'rEGION EP'

 group by CGS.Description, CD.VValue'

2 个答案:

答案 0 :(得分:1)

我猜这个问题出现在加入中:

 LEFT JOIN ChannelData AS CD ON CP.ID = CD.ID AND DI.CGS_ID_1 = CD.ID AND DI.CGS_ID_2 = CD.ID

除此之外,您在CGS_ID_1 OR CGS_ID_2上使用了联接,在本节中,您使用 AND 进行此操作。这是对的吗?

CP.ID = CD.ID看起来也很可疑。它看起来像是从主键到主键的连接,而不是外键的主键。

答案 1 :(得分:0)

有时,合适地加入表格不是解决方案。首先,通常建议甚至必须首先聚合并加入聚合,而不是先加入表并聚合。

然后,当我们只想检查表中的值是否存在时,我们通常希望将其作为WHERE子句中的条件,而不是连接中的条件。

有时我们希望将数据集与UNION ALL(或有时与UNION)合并。

第一个查询:每个CGS,边距和优先级的vvallue总和。好吧,CGS可以有多个边距和优先级,所以我们必须先找到它们。由于该表具有CGS_ID_1和CGS_ID_2,我们将使用UNION以获得每个CGS的边距和优先级。然后,vvalue与保证金和优先级无关;它只是每个CGS的总和,所以它将在结果中重复。

select cgs.description, di.margin, di.priority, coalesce(sum_vvalue, 0) as total
from cgs
join
(
  select cgs_id_1 as cgs_id, margin, priority from dataintegrity
  union
  select cgs_id_1 as cgs_id, margin, priority from dataintegrity
) di on di.cgs_id = cgs.id and di.priority = @priority
left join
(
  select id as cgs_id, sum(vvalue) as sum_vvalue
  from channeldata
  group by id
) cd on cd.cgs_id = cgs.id
order by cgs.description, di.margin, di.priority;

Secons查询:某个区域的每个CGS的vvallue总和。每个CGS可能有很多报告,我们必须在所需区域找到所有带有报告的CGS。这只是一次查询,应该使用INEXISTS

select cgs.description, coalesce(sum_vvalue, 0) as total
from cgs
left join
(
  select id as cgs_id, sum(vvalue) as sum_vvalue
  from channeldata
  group by id
) cd on cd.cgs_id = di.cgs_id
where cgs.id in (select cgs_id from report where description = 'REGION EP')
order by cgs.description;