我有一个每个用户的预订表:
reservations_development=# \d reservations
Table "public.reservations"
Column | Type | Modifiers
------------+---------+-----------------------------------------------------------
id | integer | not null default nextval('reservations_id_seq'::regclass)
user_id | integer |
occurrence | tsrange |
Indexes:
"reservations_pkey" PRIMARY KEY, btree (id)
"reservations_occurrence_user_id_excl" EXCLUDE USING gist (occurrence WITH &&, user_id WITH =)
我正在尝试创建每个用户的预订之间的差距/开放视图,我目前有以下查询:
CREATE OR REPLACE VIEW reservation_gaps AS (
with user_mins as (select tsrange(LOCALTIMESTAMP, min(lower(occurrence))), user_id
FROM (
SELECT user_id, occurrence
FROM reservations
WHERE lower(occurrence) >= LOCALTIMESTAMP
) as y
GROUP BY user_id
),
gaps as (select
tsrange(upper(occurrence), lead(lower(occurrence),1, LOCALTIMESTAMP + interval '1 year') over (win_user_gaps)),
user_id
from (
select user_id, occurrence
from reservations
) as x
WINDOW win_user_gaps AS (PARTITION BY user_id ORDER BY occurrence)
UNION ALL SELECT * FROM user_mins
)
select *
FROM gaps
ORDER BY user_id, tsrange
);
只要用户有一个预订,它目前会给出预期的结果,但如果用户是新的,并且当前没有被保留,我会得到一个空的结果。
我需要以某种方式将{tsrange(LOCALTIMESTAMP,LOCALTIMESTAMP +间隔' 1年'),user_id}行附加到每个用户的视图中,而无需预订,但我目前正在难以理解如何做到这一点。
由于
答案 0 :(得分:0)
您应该使用人工行将CTE更改为UNION ALL
,然后使用DISTINCT ON
为每个用户选择一行。
with user_mins as (SELECT DISTINCT ON (user_id) user_id, tsrange FROM(
select tsrange(LOCALTIMESTAMP, min(lower(occurrence))) as tsrange, user_id, 1 as priotity
FROM (
SELECT user_id, occurrence
FROM reservations
WHERE lower(occurrence) >= LOCALTIMESTAMP
) as y
GROUP BY user_id
UNION ALL
SELECT user_id, tsrange(LOCALTIMESTAMP, LOCALTIMESTAMP + interval '1 year'),
0
FROM users)
ORDER BY user_id, priority DESC
)
答案 1 :(得分:0)
with this_year as (
select tsrange(
date_trunc('year', current_date)::timestamp,
date_trunc('year', current_date)::timestamp + interval '1' year, '[)'
) as this_year
), gaps as (
select
user_id,
this_year - tsrange(lower(occurrence), 'infinity', '[]') lower_range,
this_year - tsrange('-infinity', upper(occurrence), '[]') upper_range,
this_year
from
reservations
cross join
this_year
)
select *
from (
select
user_id,
upper_range *
lead (lower_range, 1, this_year)
over (partition by user_id order by lower_range, upper_range)
as gap
from gaps
union (
select distinct on (user_id)
user_id,
tsrange(
lower(this_year),
coalesce(upper(lower_range), upper(this_year)),
'[)'
) as gap
from gaps
order by user_id, lower_range
)
) s
where gap != 'empty'
order by user_id, gap