SQL выбирает дату по месяцам и годам, но выбирает другие строки месяца/года по соотношению столбцов

#sql #postgresql

Вопрос:

У меня в базе данных есть следующий пример:

workshop_class_id workshop_session_id workshop_class_date
209 29 2021-06-20
210 29 2021-06-21
213 31 2021-06-30
211 30 2021-06-30
214 31 2021-07-01
212 30 2021-07-03
219 33 2021-07-12

Я хотел бы выбрать по месяцам и годам, например, июнь 2021 года, но если строки имеют отношение к workshop_session_id и даже если дата не в июне 2021 года, я хотел бы иметь эти строки.

В примере у меня есть две строки в июле, связанные с датами в июне, будет исключена только строка с workshop_session_id 33.

Я использую PostgreSQL.

Комментарии:

1. Спасибо всем огромное за ваши ответы! Принятый ответ-это тот, который наилучшим образом соответствует моей рабочей среде.

Ответ №1:

Таким образом, БД может использовать возможный индекс на workshop_class_date

 SELECT *
FROM yourTable
WHERE workshop_session_id IN (
   SELECT t1.workshop_session_id 
   FROM yourTable t1 
   WHERE t1.workshop_class_date BETWEEN date '2021-06-01' AND date `2021-06-30`) ;
 

Комментарии:

1. Спасибо вам за ваше предложение! Это действует как заклинание.

Ответ №2:

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

Решение с демонстрационными запросами:

 Create table myTable (workshop_class_id int, workshop_session_id int, workshop_class_date date);
    
    Insert into myTable values(209, 29, '2021-06-20');
    Insert into myTable values(210, 29, '2021-06-21');
    Insert into myTable values(213, 31, '2021-06-30');
    Insert into myTable values(211, 30, '2021-06-30');
    Insert into myTable values(214, 31, '2021-07-01');
    Insert into myTable values(212, 30, '2021-07-03');
    Insert into myTable values(219, 33, '2021-07-12');
    
    Select *
    from myTable tab
    join 
    (Select distinct workshop_Session_ID from myTable 
    where date_part('month',workshop_class_date) = 6 
    and date_part('year',workshop_class_date) = 2021
    ) sid on tab.workshop_Session_ID = sid.workshop_Session_ID 
 

Ответ №3:

Другой вариант-использовать аналитическую функцию для подсчета количества вхождений, а затем отфильтровать по дате или количеству вхождений

 with a as (
  select t.*, count(*) over(partition by workshop_session_id) as cnt
  from your_table t
)
select *
from a
where workshop_class_date between date '2021-06-01' and date '2021-06-30'
  or cnt > 1
 

Ответ №4:

Я бы предложил использовать здесь существующую логику:

 SELECT t1.*
FROM yourTable t1
WHERE
    DATE_TRUNC('month', t1.workshop_class_date)::date  = '2021-06-01' OR
    EXISTS (SELECT 1 FROM yourTable t2
            WHERE t2.workshop_session_id = t1.workshop_session_id AND
                  t2.workshop_class_id <> t1.workshop_class_id AND
                  DATE_TRUNC('month', t2.workshop_class_date)::date  = '2021-06-01');
 

введите описание изображения здесь


ДЕМОНСТРАЦИЯ

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