У меня есть временная метка действия пользователя. И несколько временных интервалов, когда у пользователя есть права на выполнение действия. Мне нужно проверить, находится ли временная метка этого действия хотя бы в одном из временных интервалов или нет.
Таблица с пользователями:
CREATE TABLE ausers (
id serial PRIMARY KEY,
user_name VARCHAR(255) default NULL,
action_date TIMESTAMP
);
INSERT INTO ausers VALUES(1,'Jhon', '2018-02-21 15:05:06');
INSERT INTO ausers VALUES(2,'Bob', '2018-05-24 12:22:26');
#|id|user_name|action_date
----------------------------------
1|1 |Jhon |21.02.2018 15:05:06
2|2 |Bob |24.05.2018 12:22:26
Таблица с грантами:
CREATE TABLE user_grants (
id serial PRIMARY KEY,
user_id INTEGER,
start_date TIMESTAMP,
end_date TIMESTAMP
);
INSERT INTO user_grants VALUES(1, 1, '2018-01-01 00:00:01', '2018-03-01 00:00:00');
INSERT INTO user_grants VALUES(2, 1, '2018-06-01 00:00:01', '2018-09-01 00:00:00');
INSERT INTO user_grants VALUES(3, 2, '2018-01-01 00:00:01', '2018-02-01 00:00:00');
INSERT INTO user_grants VALUES(4, 2, '2018-02-01 00:00:01', '2018-03-01 00:00:00');
#|id|user_id|start_date |end_date
------------------------------------------------------
1|1 |1 |01.01.2018 00:00:01 |01.03.2018 00:00:00
2|2 |1 |01.06.2018 00:00:01 |01.09.2018 00:00:00
3|3 |2 |01.01.2018 00:00:01 |01.02.2018 00:00:00
4|4 |2 |01.02.2018 00:00:01 |01.03.2018 00:00:00
Запрос:
select u.user_name,
case
when array_agg(gr.range) @> array_agg(tstzrange(u.action_date, u.action_date, '[]')) then 'Yes'
else 'No'
end as "permition was granted"
from ausers u
left join (select tstzrange(ug.start_date, ug.end_date, '[]') as range, ug.user_id as uid
from user_grants ug) as gr on gr.uid = u.id
group by u.user_name;
Результат:
#|user_name|permition was granted
---------------------------------
1|Bob |No
2|Jhon |No
Метка времени '01 .02.2018 15:05:06 'находится внутри "01.01.2018 00:00:01,01.03.2018 00:00:00 », поэтому у« Боба »были права на выполнение действия, и где в первой строке должно быть« Да », а не« Нет ».
Ожидаемый результат будет следующим:
#|user_name|permition was granted
---------------------------------
1|Bob |Yes
2|Jhon |No
Я пытался проверить, как это:
select array_agg(tstzrange('2018-02-21 15:05:06', '2018-02-21 15:05:06', '[]')) <@ array_agg(tstzrange('2018-01-01 00:00:01', '2018-03-01 00:00:01', '[]'));
#|?column?
----------
|false
Результат "ложь". Но если удалить функцию array_agg
select tstzrange('2018-02-21 15:05:06', '2018-02-21 15:05:06', '[]') <@ tstzrange('2018-01-01 00:00:01', '2018-03-01 00:00:01', '[]');
#|?column?
----------
|true
Работает нормально - результат "true". Почему? Что не так с array_agg?
Я должен использовать array_agg, потому что у меня есть несколько временных интервалов для сравнения.
Мне нужно сделать "поддельный" временной интервал
array_agg(tstzrange(u.action_date, u.action_date, '[]'))
изодна временная метка, потому что оператор @> не позволяет сравнивать временную метку и массив интервалов временных меток. Как сравнить эту дату с интервалом времени, по крайней мере, на временном интервале?