У меня есть список id
:
select id from id where sid = 2403
Вышеприведенное просто возвращает список id
. например id = 401434786, 401434787, 401434788 и т. д.
Когда я запускаю один из этих id
в своей таблице tval
, я получаю:
select * from tval where id = 401434786;
Я получил:
id fid ts val
401434786 3765 2019-05-14 00:00:00.000 2019-11-18 00:00:00.000
401434786 3771 2019-11-18 00:00:00.000 2019-11-18 00:00:00.000
401434786 3782 2019-05-14 00:00:00.000 2019-11-18 00:00:00.000
Моя цель — отфильтровать список id
, выбрав только те, в которых val
из fid = 3771
и fid = 3782
НЕ совпадают.
У меня есть этот запрос, который делает это:
select distinct t.id from tval t
where (select min(t1.val) from tval t1
where t1.id = t.id and t1.fid = 3771)
!=(select min(t1.val) from tval t1
where t1.id = t.id and t1.fid = 3782)
and id in (select id from id where sid = 2403);
Однако я хочу изменить запрос или написать совершенно новый, чтобы отфильтровать список id
до тех, где различаются только Month
или Year
, но если Month
и Year
одинаковы, но Day
отличается, тогда оставь это.
В приведенном выше запросе он фильтрует id
, где, если Month
и Year
одинаковы, но Day
отличается, он все равно включает его в выходные данные, но я этого не хочу. Мне нужны только id
, где Month
или Year
разные.
Я надеюсь, что вышеизложенное имеет смысл, и я очень ценю любую помощь!
Для значения даты используйте экстракт(месяц из иногдатамп) для извлечения месяца, экстракт(год из иногдатамп) для извлечения года и экстракт(день из иногдатамп) для дня месяца.
Почти то же самое вы можете использовать date_part('месяц', иногдаtamp) и т.д.
Итак, в пунктеwhere,
Select *
From a
Where extract(month from a.sometimestamp) = 4
And extract(year from a.sometimestamp) = 2024
Я добавил пример.
Используйте date_trunc(). Как только вы сократите две даты/временные метки до месяца, они станут эквивалентными, если их год и месяц совпадают:
select distinct t.id from tval t
where (select min(date_trunc('month',t1.val)) from tval t1
where t1.id = t.id and t1.fid = 3771)
!=(select min(date_trunc('month',t1.val)) from tval t1
where t1.id = t.id and t1.fid = 3782)
and id in (select id from id where sid = 2403);
Это сравнение фактически игнорирует не только день, но и все, что ниже точности месяца, а также дни, часы, минуты, секунды и дроби.
Если бы это min()
было своего рода компромиссом, в то время как вы на самом деле хотите избежать id
наличия любой пары fid 3771 и 3782 в одном и том же месяце (а не только при их самом раннем появлении для данного id
), вы могли бы вместо этого использовать перекрытие массива &&:
select distinct t.id from tval t
where not
(select array_agg(date_trunc('month',t1.val)) from tval t1
where t1.id = t.id and t1.fid = 3771)
&&(select array_agg(date_trunc('month',t1.val)) from tval t1
where t1.id = t.id and t1.fid = 3782)
and id in (select id from id where sid = 2403);
Что, вероятно, могло бы быть быстрее, если бы not exists
:
select distinct t.id from tval t
where not exists
(select from tval t1 where t1.id = t.id and t1.fid = 3771
where date_trunc('month',t1.val) in
( select date_trunc('month',t1.val) from tval t1
where t1.id = t.id and t1.fid = 3782) )
and id in (select id from id where sid = 2403);
Есть идеи, как включить его в запрос выше? Я тоже могу использовать
TO_CHAR
, чтобы преобразовать его, но мне сложно собрать все это воедино.