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 月 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,則必須在外部使用 case 重寫表達式,並為 null 新增分支。

如果您需要它純粹是 select 語句,只需對 case 語句中的日期進行硬編碼,而不是使用變數。

相關內容