2016-07-07 2 views
1

У меня возникли проблемы с построением запроса, который бы выполнил что-то относительно простое.Простые левые соединения на одном столе

У меня есть одна таблица, которую мы можем назвать data. В этой таблице есть столбец date и столбец, который указывает записи как данные daily или monthly.

Я хочу получить все daily записей, а также monthly записей, в которых ежедневных записей не существует. Пример: если ежедневно запись 2016-01-10 существует, то я не хочу, чтобы получить ежемесячный отчет о 2016-01-01

Я чувствую, как этот следующий запрос должен достичь этой цели, но я не могу понять, почему он возвращает слишком много строк (дубликаты) и при дедуплировании не возвращает желаемый набор.

SELECT daily.* 
FROM data daily 
LEFT JOIN data monthly 
    ON date_trunc('month', daily.date) != date_trunc('month', monthly.date) 
AND monthly.interval='monthly' 
WHERE daily.interval='daily' 
    AND monthly.interval='monthly' 

Предназначенное поведение, чтобы вернуть все записи из левых, ежедневных данных, а также присоединиться на условиях, в которых нет ежемесячных записей не возвращаются, которые имеют тот же месяц, как и любые ежедневные записи.

+0

Но данные в каждой таблице то же самое, конечно, вы будете иметь записи, которые соответствуют в обоих , –

+0

Когда LEFT JOIN, поместите условия правого бокового стола в предложение ON, чтобы получить истинное поведение левого соединения. (Когда в ГДЕ вы получаете регулярный результат внутреннего соединения.) – jarlh

ответ

1
select * 
from data d 
where 
    interval = 'daily' 
    or 
    interval = 'monthly' 
    and 
    not exists (
     select 1 from data 
     where 
      date_trunc('month', d.date) = date_trunc('month', date) 
      and interval = 'daily' 
    ) 
1

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

SELECT monthly.* 
FROM data monthly 
where monthly.interval='monthly' and to_char(monthly.date, 'YYYY-MM') not in 
(select to_char(daily.date, 'YYYY-MM') from data daily where daily.interval='daily') 
UNION 
SELECT daily.* 
FROM data daily 
where daily.interval='daily' 
+0

Спасибо, редактируя инструкцию select ежемесячно. * Работает. Я изменил to_char на date_trunc, и запрос выполняется быстрее. –

+0

Рад, что это сработало для вас, но как вы на самом деле сравниваете, что месяц принадлежит к тому же году? Вы пишете две функции date_trunc? –

+1

Я считаю, что использование date_trunc фактически выбирает дату в начале любого выбранного вами интервала. Поэтому использование date_trunc ('month', 2016-5-30) должно вернуть 2016-5-1 –

Смежные вопросы