Определение того, содержит ли месяц записи

У меня есть список журналов с отметками времени, и я хотел бы, чтобы запрос возвращал 12 логических значений, указывающих, содержит ли определенный месяц какие-либо журналы для каждого месяца года (начиная с января), то есть:

(True, False, False, True, False ..., True)

В настоящее время у меня есть следующий запрос, который покажет мне все месяцы, содержащие данные:

SELECT DISTINCT(EXTRACT(MONTH FROM logdate)) AS month
FROM mytable
WHERE EXTRACT(YEAR FROM logdate) = '2009'
ORDER BY month;

Результатом которого является список месяцев, содержащий данные, например:

(1, 2, 5, 6, 12)

Я просто не могу решить следующий шаг - любые указатели будут оценены.

Я использую PostgreSQL v8.4.2. Спасибо.


person Noah    schedule 23.03.2010    source источник


Ответы (3)


Переместите WHERE в условие JOIN:

SELECT DISTINCT
    CASE
        WHEN EXTRACT(MONTH FROM logdate) IS  NULL THEN false
        ELSE true
    END,
    y AS month
FROM
    mytable 
        RIGHT JOIN 
        (SELECT generate_series(1,12)) AS x(y) ON ((EXTRACT(MONTH FROM logdate)) = y AND EXTRACT(YEAR FROM logdate) = '2009')
ORDER BY 
    month ASC;

Условие года применяется только к совпадающим записям.

person Frank Heikens    schedule 24.03.2010

Используйте generate_series():

SELECT
    CASE
        WHEN EXTRACT(MONTH FROM logdate) IS NULL THEN false
        ELSE true
    END,
    y AS month
FROM
    mytable RIGHT JOIN generate_series(1,12) AS x(y) ON EXTRACT(month FROM logdate) = y
WHERE 
    EXTRACT(YEAR FROM logdate) = '2009';
person Frank Heikens    schedule 23.03.2010
comment
При выполнении этого запроса он дает мне тысячи строк в форме (кейс, месяц) в качестве результата:/ - person Noah; 23.03.2010
comment
Попробуйте DISTINCT, я им не пользовался. - person Frank Heikens; 23.03.2010
comment
С отличными он дает истину рядом со всеми месяцами со значениями, но месяцы без значений исключаются из списка (вместо заданного f). - person Noah; 24.03.2010

Я не уверен, что это самое элегантное решение, но оно должно работать (проверено на Postgres):

SELECT (CASE WHEN max(sub.jan)=1 THEN true ELSE false END) AS jan,
       (CASE WHEN max(sub.feb)=1 THEN true ELSE false END) AS feb,
       ...
FROM
(
    SELECT (CASE WHEN (EXTRACT(MONTH FROM logdate))=1 THEN 1 ELSE 0 END) AS jan,
    (CASE WHEN (EXTRACT(MONTH FROM logdate))=2 THEN 1 ELSE 0 END) AS feb,
    ...
    FROM mytable
    WHERE EXTRACT(YEAR FROM logdate) = '2009'
) as sub
person Chris Lercher    schedule 23.03.2010