sql - преобразование года в день/месяц

sql - преобразование года в день/месяц

предположим, у меня есть следующая таблица

+-----------+-------------+
|    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 вместо использования переменных.

Связанный контент