#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');
ДЕМОНСТРАЦИЯ
Логика здесь говорит о том, чтобы сохранить и июнь или любую запись из любого другого месяца/года, для которого мы можем найти общий идентификатор сеанса семинара с записью июня.