sql >> Database teknologi >  >> RDS >> PostgreSQL

Lagring og forespørgsel efter intervaltræ i PostgreSQL

Du kan bruge intervaldatatyperne og gemme hver usammenhængende type i en række.

Til din prøve:

-- The table
CREATE TABLE sets(id text, range int4range);
-- Values of set A
INSERT INTO sets VALUES('A', '[1,1]'),('A','[7,7]'),('A','[9,13]');
-- Values of set B
INSERT INTO sets VALUES('B','[1,1]'),('B','[7,7]'),('B','[10,10]');
 

For at kontrollere, om B er en delmængde af A, kan du forbinde begge med alle tupler, hvor A's område indeholder B's område:

 SELECT b.range
 FROM sets b JOIN sets a
     ON a.range @> b.range
 WHERE a.id='A' AND b.id='B'
 

Med det kan du kontrollere, om alle værdierne fra sæt B er i ovenstående resultat (hvilket vil betyde, at alle områderne af B er indeholdt af mindst ét ​​område af A):

 SELECT NOT EXISTS(
     SELECT 1 FROM sets q WHERE q.id='B' AND q.range NOT IN (
         SELECT b.range
         FROM sets b JOIN sets a
             ON a.range @> b.range
         WHERE a.id='A' AND b.id='B'
     ));
 

For at få krydset, kan du krydsforbinde begge og ekskludere de tomme:

SELECT * FROM ( SELECT a.range * b.range AS intersec FROM sets a CROSS JOIN sets b WHERE a.id='A' AND b.id='B' ) i WHERE NOT isempty(i.intersec);

Et problem ved denne tilgang er, at du kun skal holde usammenhængende rangeS gennem forskellige tupler. For eksempel skal området [1,5] og [4,7] fra et sæt ligge i en tupel med kun [1,7]. For at være sikker på det, kan du indsætte dem i en midlertidig tabel (mens du indsætter eller opdaterer), de krydser selve bordet med tupler, der overlapper, og de slutter sig til dem og holder de andre, som de er.



  1. PHP Uddrag koder fra TextArea og videregive til Mysql SELECT IN Query

  2. Codeigniter $this->db->reconnect(); brug

  3. Oracle underforespørgsel kan ikke se variablen fra den ydre blok 2 niveauer og op

  4. Hvordan kan jeg bekræfte butikskoden i mysql og opdatere tabellen, hvis resultatet returnerer sandt