как получить 0 вместо значений NULL, если набор результатов равен 0 (считая рабочих дней) - PullRequest
0 голосов
/ 23 мая 2018

Я считаю рабочие дни между двумя датами.Некоторые из моих результатов законно должны быть 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

Source 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 голосов
/ 23 мая 2018

Переместил 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
0 голосов
/ 23 мая 2018

Я бы предложил несколько иной подход.CROSS APPLY - это МС, и мне сложно рассуждать.Не похоже, что он выигрывает у вас больше, чем обычные подзапросы.Это намного легче для меня, и он должен выполнять свою работу:

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 оценивается как истина.В этих случаях счетчик даты выбирается как NULL напрямую, без подзапроса.В противном случае соответствующий агрегированный (под) запрос выполняется для таблицы CALENDAR.

0 голосов
/ 23 мая 2018
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
  ) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...