Postgres odstranění "menší" se pohybuje od většího rozsahu a vrátit úhrn se pohybuje

0

Otázka

Mám rezervační systém, který pracuje s manželskou rezervace. Osoba, knihy, pokoj pro tsrange, a pak můžete rezervovat schůzky na vrcholu se, že rezervaci pokoje. Byl jsem schopen, aby se omezení práce v pořádku, samozřejmě tsrange události musí být obsaženy v rezervaci tsrange.

Teď jsem třeba dotaz, který vrátí tsranges[] se pohybuje, že rezervace je v klidovém stavu, tedy žádné schůzky byly provedeny v té době ještě, ale nejsem si jistý, jak to udělat, že...No, mám hrubou představu o tom, jak jsem mohl realizovat to v plpgsql opakování v průběhu schůzky, ale zajímalo by mě, jestli tam je více elegantní řešení s plain SQL, možná pomocí rekurzivní CTE nebo window funkce?

Například zvažte mám rezervaci na dosah: '[2010-01-01 08:00, 2010-01-01 18:00)'.

A následující události v rezervaci: '[2010-01-01 08:00, 2010-01-01 09:00)';'[2010-01-01 11:00, 2010-01-01 12:00)';'[2010-01-01 14:00, 2010-01-01 17:00)'

Výstup takové funkci být něco jako: '[2010-01-01 09:00, 2010-01-01 11:00)','[2010-01-01 12:00, 2010-01-01 14:00)','[2010-01-01 17:00, 2010-01-01 18:00)'

Zde je ukázka dbfiddle s zjednodušeného schématu :

create table reservation (
  id numeric,
  room_id numeric,
  during tsrange
 );
 
 create table appointment (
   id serial,
   on_reservation numeric,
   during tsrange
 );
 
 insert into reservation (id, room_id, during)
        VALUES (1, 1, '[2010-01-01 08:00, 2010-01-01 18:00)');
        
insert into appointment (id, on_reservation, during)
        VALUES (2, 1, '[2010-01-01 08:00, 2010-01-01 09:00)');

insert into appointment (id, on_reservation, during)
        VALUES (3, 1, '[2010-01-01 10:00, 2010-01-01 12:00)');

insert into appointment (id, on_reservation, during)
        VALUES (4, 1, '[2010-01-01 14:00, 2010-01-01 17:00)');

Já jsem stále ještě není seznámen s multi-range přidána podpora v pg14, ale pokud to dělá věci jednodušší, můžu upgradovat...

1

Nejlepší odpověď

1

S PostgreSQL v14 a vaše data model, který by mohl být stejně jednoduché jako

SELECT r.id,
       /* convert the reservation to a multirange */
       tsmultirange(r.during)
       -
       /* aggregate the appointments to a multirange */
       range_agg(a.during)
       AS free_slots
FROM reservation AS r
   JOIN appointment AS a ON a.on_reservation = r.id
GROUP BY r.id, r.during;
2021-10-28 02:49:39

V jiných jazycích

Tato stránka je v jiných jazycích

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................