左加入日期缺失

时间:2019-05-14 11:28:25

标签: sql sql-server join

我有一个数据表(SELECT * FROM OPENROWSET('SQLNCLI', 'Server=server.database.windows.net;Database=DBName;UID=Admin;PWD=********, 'select * from tablename;') ),其中有列(FACT.UnitDataDayCalendarDate),但缺少一些数据:

SalesQty

我有另一个表(DayCalendarDate SalesQty 2019-05-13 00:00:00.0000000 36 2019-05-11 00:00:00.0000000 105 2019-05-10 00:00:00.0000000 50 2019-05-09 00:00:00.0000000 30 2019-05-08 00:00:00.0000000 22 ),其中有1列(DIM.DayCalendar)是连续的,因此没有丢失的日期:

Date

我想加入这两个表并在Date 2019-05-13 00:00:00.0000000 2019-05-12 00:00:00.0000000 2019-05-11 00:00:00.0000000 2019-05-10 00:00:00.0000000 2019-05-09 00:00:00.0000000 2019-05-08 00:00:00.0000000 中用0.0填写缺失的日期(2019-05-12)。到目前为止,我有以下内容:

FACT.UnitData

但这不会用0.0填写缺失的日期(2019-05-12)。

感谢您的帮助。

2 个答案:

答案 0 :(得分:4)

您只需要coalesce()吗?

SELECT c.Date, COALESCE(ud.SalesQty, 0) as SalesQty
FROM DIM.DayCalendar c LEFT JOIN
     FACT.UnitData AS ud
     ON c.Date = ud.DayCalendarDate
ORDER BY c.Date DESC;

还要注意,ORDER BY使用日历日期,而不是参考值。毕竟,这将是NULL,所以它的顺序不正确。

答案 1 :(得分:1)

DECLARE @unit_id INT = 71907
DECLARE @location_id INT = 59

SELECT dc.Date, ud.SalesQty
 FROM DIM.DayCalendar AS dc
  LEFT JOIN FACT.UnitData AS ud
   ON dc.Date = ud.DayCalendarDate
 WHERE ud.UnitID = @unit_id AND ud.LocationID = @location_id
 ORDER BY dc.Date DESC

截至目前为止我所看到的查询(我看不到NOLOCK,也许已经进行了其他编辑)将在SQL中执行,如下所示:

首先,将处理来自DIM.DayCalendar AS dc的数据。

此表上没有进行任何过滤,因此在此步骤中将检索所有行。

接下来,处理到FACT.UnitData AS ud的联接。作为LOJ,第一个表中的所有行都将保留(仍不进行过滤),并且第二个表中的行将被合并。这可能导致第一个表中的行出现多次(即,表中每个连接的行均出现一次)第二张表)。更重要的是,如果在第二张表中未找到任何行,则它们的值将设置为NULL。

接下来,将考虑WHERE子句:ud.UnitID = @unit_id AND ud.LocationID = @location_id。 “ ud”是第二个表,因此将过滤掉所有不符合这些条件的行。这意味着当找到NULL时,where子句将解析为False,因此将从第二张表中未检索到数据的所有行都将被过滤掉。

这就是您丢失日期的方式–外部联接成功,但是随后删除了所有“找不到数据”行。下一个效果与将其设为内部联接一样。

最直接的解决方法是将filterig条件移到join子句中,如下所示:

SELECT dc.Date, ud.SalesQty
 FROM DIM.DayCalendar AS dc
  LEFT JOIN FACT.UnitData AS ud
   ON dc.Date = ud.DayCalendarDate
    AND ud.UnitID = @unit_id
    AND ud.LocationID = @location_id
 ORDER BY dc.Date DESC

这将在第二个表中找到较少的联接行,但是由于它是外部联接,因此第一个表中的所有行都将包含在结果集中。

另一种版本是在where子句中检查NULL:

SELECT dc.Date, ud.SalesQty
 FROM DIM.DayCalendar AS dc
  LEFT JOIN FACT.UnitData AS ud
   ON dc.Date = ud.DayCalendarDate
 WHERE ud.UnitID = isnull(@unit_id, ud.UnitID)
  AND ud.LocationID = isnull(@location_id, ud.LocationID)
ORDER BY dc.Date DESC

请注意,这可能会比第一个查询执行得差一些。这两种查询都很难阅读和理解,但是对于复杂的查询,这将会发生。