我计算两个日期之间的工作日。我的一些结果合法地应该是NULL,但有些返回为NULL,而应该是0.这是我使用的查询:
SELECT
ROW_NUMBER() OVER (ORDER BY Date_key asc) BusinessDaysID,
BSDAYS * CASE WHEN B.ClosingDate > B.ApprovalDate THEN -1 ELSE 1 END FinaldDateCount
FROM
DIM_DATE B
CROSS APPLY (
SELECT NULLIF(COUNT(*),0) BSDAYS
FROM CALENDAR
WHERE
BSDAYS >= CASE WHEN B.ClosingDate > B.ApprovalDate THEN B.ApprovalDate ELSE B.ClosingDate END
AND BSDAYS < CASE WHEN B.ClosingDate > B.ApprovalDate THEN B.ClosingDate ELSE B.ApprovalDate END
) R1
来源DIM_DATE B示例:
Date_Key ClosingDate ApprovalDate
38544 2018-01-18 2018-02-05
38545 NULL NULL
38546 NULL NULL
38547 NULL NULL
38548 2018-05-01 2018-05-01
38549 NULL NULL
38550 NULL NULL
38551 NULL NULL
38552 2018-03-08 2018-03-15
38553 NULL NULL
38554 NULL 2018-04-25
38555 NULL NULL
源日历示例:
BSDAYS
2018-04-27
2018-04-30
2018-05-01
2018-05-02
2018-05-03
2018-05-04
2018-05-07
2018-05-08
2018-05-09
2018-05-10
2018-05-11
2018-05-14
2018-05-15
2018-05-16
2018-05-17
2018-05-18
2018-05-21
2018-05-22
2018-05-23
这就是我现在所得到的:
BusinessDaysID FinalDateCount
38544 12
38545 NULL
38546 NULL
38547 NULL
38548 NULL
38549 NULL
38550 NULL
38551 NULL
38552 5
38553 NULL
38554 NULL
38555 NULL
我想:
BusinessDaysID FinalDateCount
38544 12
38545 NULL
38546 NULL
38547 NULL
38548 0
38549 NULL
38550 NULL
38551 NULL
38552 5
38553 NULL
38554 NULL
38555 NULL
如果您注意到Date_Key 38548将显示为NULL并且应为0。
我的查询有什么问题,我该如何解决?
答案 0 :(得分:1)
移动NullIF并在顶部查询中添加了一点逻辑。
SELECT
ROW_NUMBER() OVER (ORDER BY Date_key asc) BusinessDaysID,
CASE
WHEN B.ApprovalDate=B.ClosingDate THEN 0
ELSE NULLIF(BSDAYS,0)
END * CASE WHEN B.ClosingDate > B.ApprovalDate THEN -1 ELSE 1 END FinaldDateCount
FROM
DIM_DATE B
CROSS APPLY (
SELECT COUNT(*) BSDAYS
FROM CALENDAR
WHERE
BSDAYS >= CASE WHEN B.ClosingDate > B.ApprovalDate THEN B.ApprovalDate ELSE B.ClosingDate END
AND BSDAYS < CASE WHEN B.ClosingDate > B.ApprovalDate THEN B.ClosingDate ELSE B.ApprovalDate END
) R1
答案 1 :(得分:1)
我建议采用一种不同的方法。 CROSS APPLY
是一个MS-ism,我有点难以推理。它看起来并不像普通的子查询那样获得了很多东西。这对我来说更容易阅读,它应该做的工作:
SELECT
Date_Key AS BusinessDaysID,
CASE
WHEN B.ApprovalDate <= B.ClosingDate THEN
(SELECT COUNT(*) FROM Calendar C
WHERE C.BSDAYS BETWEEN B.ApprovalDate AND B.ClosingDate)
WHEN B.ApprovalDate > B.ClosingDate THEN
(SELECT -COUNT(*) FROM Calendar C
WHERE C.BSDAYS BETWEEN B.ClosingDate AND B.ApprovalDate)
ELSE
NULL
END AS FinalDateCount
FROM
DIM_DATE B
请注意,它依赖于以下事实:当B.ClosingDate
和B.ApprovalDate
中的至少一个为NULL时,B.ApprovalDate <= B.ClosingDate
和B.ApprovalDate > B.ClosingDate
都不会计算为true。在这些情况下,日期计数直接选为NULL,没有子查询。否则,在CALENDAR表上执行适当的聚合(子)查询。
答案 2 :(得分:0)
SELECT
ROW_NUMBER() OVER (ORDER BY Date_key asc) BusinessDaysID,
BSDAYS * CASE WHEN B.ClosingDate = B.ApprovalDate THEN 0
WHEN B.ClosingDate > B.ApprovalDate THEN -1
ELSE 1
END FinaldDateCount
FROM
DIM_DATE B
CROSS APPLY (
SELECT NULLIF(COUNT(*),0) BSDAYS
FROM CALENDAR
WHERE
BSDAYS >= CASE WHEN B.ClosingDate > B.ApprovalDate THEN B.ApprovalDate ELSE B.ClosingDate END
AND BSDAYS < CASE WHEN B.ClosingDate > B.ApprovalDate THEN B.ClosingDate ELSE B.ApprovalDate END
)