Классификация месяцев по периодам

Предположим, у меня есть данные за 2 года. С января 2010 года по декабрь 2011 года.
Я хочу классифицировать каждый месяц как период. Таким образом, январь 2010 будет моим 1, февраль 2010 моим 2, и так далее до декабря 2011 года мой 24 период.

Я знаю, что мог бы сделать что-то вроде:

select 
    year,mn, 
    case when year=2010 and mn=01 then 1
    else when year=2010 and mn=02 then 2
    else when year=2010 and mn=03 then 3
    //and so on until // else when year=2011 and mn=12 then 24 end 
from mytable;

Результат будет примерно таким:

year    mn  period
2010    1   1
2010    2   2
2010    3   3
2010    4   4
2010    5   5
2010    6   6
2010    7   7
2010    8   8
2010    9   9
2010    10  10
2010    11  11
2010    12  12
2011    1   13
2011    2   14
2011    3   15
2011    4   16
2011    5   17
2011    6   18
2011    7   19
2011    8   20
2011    9   21
2011    10  22
2011    11  23
2011    12  24

Я хочу избежать такого длинного и не мудрого метода.

3 ответа

Решение
select
    year, mn,
    row_number() over (order by year, mn) as period
from t

Дешевая версия для этого конкретного случая:

SELECT year, mn, (year - 2010) * 12 + mn AS period
FROM   tbl;

Это также будет учитывать месяцы, которые могут отсутствовать в ваших данных.
И это даст вам согласованные числа, даже если выбрать только несколько строк.

Нет необходимости в модных оконных функциях. Просто сделай это простым способом. Для данного {epoch-year} а также {epoch-month} (например, 2010 и 1 соответственно), формула

( ( 12*year + mn ) - ( 12*{epoch-year} + {epoch-month} )

даст вам смещение в месяц от эпохи. Добавьте 1 к этому, и у вас есть номер периода. Это приводит вас к чему-то вроде этого:

select year ,
       mn   ,
       (   ( 12*year         + mn            )
         - ( 12*{epoch-year} + {epoch-month} )
       ) + 1 as period
       ...
from some-table
where   year > {epoch-year}
   OR ( year = {epoch-year} and mn >= {epoch-month} )

Если вы не имеете в виду конкретную эпоху, вы можете сделать что-то вроде этого:

select t.year ,
       t.mn   ,
       (   ( 12*year       + mn          )
         - ( 12*epoch.year + epoch.month )
       ) + 1 as period
       ...

from       ( select year,mn
             from some-table
             order by year , mn
             limit 1
           ) epoch
cross join some-table t

Следует отметить, что можно придумать формулу для нумерации периодов, основанных на длинах периодов, превышающих 1 месяц: просто вычислите смещение в месяцах и используйте целочисленное деление, чтобы разделить это смещение на длину периода в месяцах, тем самым перейдя к последовательному номер периода, что-то вроде

       (   ( 12*year + mn )
         - ( 12*2010 + 1  )
       ) DIV 3 + 1 as period

должен дать вам периоды продолжительностью 3 месяца

Другие вопросы по тегам