结果集为0时如何检索0而不是NULL值(计算工作日)

时间:2018-05-23 15:49:48

标签: sql sql-server tsql null

我计算两个日期之间的工作日。我的一些结果合法地应该是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。

我的查询有什么问题,我该如何解决?

3 个答案:

答案 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.ClosingDateB.ApprovalDate中的至少一个为NULL时,B.ApprovalDate <= B.ClosingDateB.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
  )