предположим, у меня есть следующая таблица
+-----------+-------------+
| DAY | LEAP YEAR |
+-----------+-------------+
| 7 | true |
| 167 | false |
| 43 | true |
| 60 | true |
| 256 | false |
| 340 | false |
+-----------+-------------+
используя только функции SQL, как можно «преобразовать» эти дни года в фактические комбинации день/месяц? Результат будет примерно таким:
+-----------+-------------+------------+
| DAY | LEAP YEAR | RESULT |
+-----------+-------------+------------+
| 7 | true | 7 Jan |
| 167 | false | 16 Jun |
| 43 | true | 12 Feb |
| 60 | true | 29 Feb |
| 256 | false | 13 Sep |
| 340 | false | 6 Dec |
+-----------+-------------+------------+
решение1
Удобное свойство високосных лет заключается в том, что они все одинаковы (за исключением круглых столетних лет). Поэтому вы можете просто выбрать любой високосный или невисокосный год и получить тот же результат для всех остальных. Например, 2016 год — високосный, а 2015 — нет. Учитывая эту информацию, вы можете использовать DDD
форматировщик даты (деньгод) и используйте некоторые case
выражения, чтобы получить необходимую информацию:
SELECT TO_CHAR(
TO_DATE(TO_CHAR(day) ||
'-' ||
CASE leap_year
WHEN 'true' THEN '2016'
ELSE '2015'
END,
'DDD-YYYY'),
'dd month') AS result
FROM my_table
решение2
Быстрый и грязный способ: выберите год, который не является високосным, и год, который является високосным. Поместите дату = 1 января каждого года в две переменные. Используя оператор CASE, сложите (значение дня - 1) и любую подходящую переменную даты. Затем используйте либо оператор case, либо больше SQL, чтобы получить название месяца и день из этого выражения.
declare @normal_year_nyd date = '1-1-2015';
declare @leap_year_nyd date = '1-1-2016';
select
t.[day], -- highly suggest naming this something other than 'day' to avoid ambiguous code
t.leap_year,
datename(month, dateadd(day, t.[day] - 1,
case
when t.leap_year = 'false'
then @normal_year_nyd
when t.leap_year = 'true'
then @leap_year_nyd
end)
) as month_name,
-- do the same as above replacing "month" with "day" in the dateadd expression
from my_table t
where t.leap_year is not null and t.[day] is not null
Если вам необходимо обрабатывать значения NULL, то вам придется переписать выражения с регистром снаружи и добавить ветвь для NULL.
Если вам нужно, чтобы это был просто оператор выбора, просто жестко закодируйте даты в операторе case вместо использования переменных.