"之间"左连接中的语句返回null

时间:2017-03-31 20:30:29

标签: sql sql-server tsql left-join

好的,有GOT可以解决这个问题......对于Stack Overflow的众多专家来说,这可能是一个直接的解决方案! : - )

背景: 我正在尝试按班次创建餐馆销售报告。我有2个表...一个有 RECEIPT 详细信息(餐厅,日期,时间,收据#,金额,服务器等),另一个有 SHIFT < / strong>详细信息(餐厅,班次开始时间,轮班结束时间和班次名称)。两个表中都有 Shift Numbers ,但不幸的是,Receipts表中的 Shift Numbers 并不总是准确的,因此我不得不根据哪个存储桶提出解决方法of ShiftStart &amp; ShiftEnd ReceiptTime 落入。这个连接代码几乎可以工作:

LEFT OUTER JOIN: Receipts.Time BETWEEN ShiftDetails.ShiftStartTime AND ShiftsDetails.ShiftEndTime

但是...我的挑战是晚餐 ShiftEndTime 目前是02:00,当然, 比晚餐 ShiftStartTime of 17:31,所以任何 ReceiptTimes &#34;在&#34;之间这些小时返回空值。我还想通过避免&#34;硬编码来保持查询的动态性。 开始/结束时间,而不是使用Shift表中的那些,因为它们将来可能会被修改。

FWIW,我的数据源是带有Power BI作为前端的SQL Server,因此我可以废弃SQL代码并使用PowerQuery或DAX执行魔术......

非常感谢提前! 丹尼

2 个答案:

答案 0 :(得分:0)

以下是处理此逻辑的一种方法:

Receipts r LEFT OUTER JOIN
ShiftDetails sd
ON (sd.ShiftStartTime <= sd.ShiftEndTime AND r.Time BETWEEN sd.ShiftStartTime AND sd.ShiftEndTime) OR
    (sd.ShiftStartTime > sd.ShiftEndTime AND r.Time BETWEEN sd.ShiftEndTime AND sd.ShiftStartTime)

您可能认为自己真的不想要BETWEEN。完全在班次之间的边界上的收据将返回它们 - 因为BETWEEN包括范围的终点。

答案 1 :(得分:0)

您缺少一个函数,说明班次结束时间是否小于凌晨4:00,而不是返回第二天的日期时间。

因此它将用于以下连接:

WHERE ShiftEndDateTime <= dbo.EndShiftDateTime(@ShiftDate, @ShiftEndTime)

如果小时数小于5,则会将其推迟到第二天:

CREATE FUNCTION dbo.EndShiftDateTime(@ShiftDate Date, @ShiftTime Time) 
  RETURNS DateTime
AS
BEGIN


IF(DATEPART(HOUR, @ShiftTime) < 5)
    SET @ShiftDate =  dateadd(day, 1, @ShiftDate)

RETURN cast(@ShiftDate as datetime)  + cast(@ShiftTime as datetime)         

END

我不喜欢这样一个小时的硬编码,但它不可能永远改变。您可以使逻辑更灵活(如果是endtime&lt; starttime)但我已经看到这只会导致很难找到错误。