【问题标题】:Can not get null values with full outer join无法通过完全外连接获取空值
【发布时间】:2020-08-22 13:11:29
【问题描述】:

我正在使用 SQL Server。 我有一张表 Dim_date,所有日期均为 2020 年 5 月

Datekey
---------
20200501 
20200502
20200503
20200504
20200505
20200506
20200507
....

我有一个 Fact_Controls 表格,其中包含特定中心每天完成的控制数量。

Date_Ctl | Id_Centre | No_Controls
---------------------------
20200505| 01415     |1
20200505| 01415     |1
20200505| 01415     |1
20200506| 01415     |1
20200506| 01415     |1

我想要一个查询来显示中心已完成的控制数量,即使它是 0 或 null,例如:

Datekey | Id_Centre | No_Controls
---------------------------
20200501| 01415     |0
20200502| 01415     |0
20200503| 01415     |0
20200504| 01415     |0
20200505| 01415     |3
20200506| 01415     |2
20200507| 01415     |0
....

我正在这样做,但我没有得到我期望的结果:

select 
     dd.DateKey,
     sum(No_Controls) as total_controls
from 
      [Fact_Controls] fc
full outer join 
     [dm].[Dim_Date] dd on  fc.Date_Ctl = dd.DateKey
where 
     fc.[Id_Centre]='01415' 
    and fc.Date_Ctl between 20200501 and 20200520
    and dd.DateKey is null
group by dd.DateKey

【问题讨论】:

  • 您的WHEREfull outer join 变成left join。毕竟,fc.[Id_Centre]='01415' 意味着它不是null
  • 即将 WHERE 子句 fc 条件移至 ON 子句。
  • 所以我可以删除filter c.[Id_Centre]='01415' 并将查询封装在With 中,然后按中心过滤?
  • 这能回答你的问题吗? Full outer join not returning all rows?
  • 这是一个常见问题解答。在考虑发布之前,请阅读您的教科书和/或手册和谷歌任何错误消息或您的问题/问题/目标的许多清晰、简洁和精确的措辞,有和没有您的特定字符串/名称和站点:stackoverflow.com 和标签;阅读许多答案。如果您发布问题,请使用一个短语作为标题。反映你的研究。请参阅How to Ask 和投票箭头鼠标悬停文本。

标签: sql sql-server join left-join outer-join


【解决方案1】:

外部连接行在没有匹配行的列中有空值。所以这个

where fc.[Id_Centre]='01415' and fc.Date_Ctl between 20200501 and 20200520

将删除所有外部连接的 fc 行。

这个

where dd.DateKey is null

另一方面,将删除所有未外部连接的 dd 行。

此外,为什么要使用完全外连接?日期表不应该包含所有日期吗?看来您只需要一个左外连接:

select
  dd.datekey,
  sum(fc.no_controls) as total_controls
from dm.dim_date dd 
left join fact_controls fc on  fc.date_ctl = dd.datekey and fc.id_centre = '01415' 
where dd.datekey between '20200501' and '20200520'
group by dd.datekey
order by dd.datekey;

或者(加入前的聚合):

select dd.datekey, fc.total_controls
from dm.dim_date dd 
left join
(
  select date_ctl, sum(no_controls) as total_controls
  from fact_controls
  where id_centre = '01415'
  group by date_ctl
) fc on  fc.date_ctl = dd.datekey
where dd.datekey between '20200501' and '20200520'
order by dd.datekey;

或者(直接按日期行聚合):

select dd.datekey, fc.total_controls
from dm.dim_date dd 
outer apply
(
  select sum(no_controls) as total_controls
  from fact_controls
  where id_centre = '01415'
  and by date_ctl = dd.datekey
) fc
where dd.datekey between '20200501' and '20200520'
order by dd.datekey;

您可以使用 coalesce 将结果中的空值变为零。

如果datekey + id_centre 在您的表中是唯一的fact_controls,那么您当然根本不需要聚合 (SUM)。

【讨论】:

  • 非常感谢,您的回答很清楚,效果很好。
【解决方案2】:

请使用外部应用

SELECT * FROM [Dim_Date] D 
OUTER APPLY 
   ( 
   SELECT * FROM [Fact_Controls] F 
   WHERE F.Date_Ctl = D.DateKey 
   ) A 
GO

【讨论】:

    猜你喜欢
    • 2022-11-14
    • 1970-01-01
    • 2018-05-01
    • 1970-01-01
    • 2019-11-25
    • 2015-12-11
    • 2012-01-06
    • 2013-03-11
    相关资源
    最近更新 更多