sql >> Database >  >> RDS >> PostgreSQL

Intervalboom opslaan en opvragen in PostgreSQL

U kunt de gegevenstypes voor het bereik gebruiken en elk onsamenhangend type op een rij opslaan.

Voor uw voorbeeld:

-- 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]');

Om te controleren of B een subset van A is, kun je beide samenvoegen met alle tuples waarvan het bereik van A het bereik van B bevat:

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

Hiermee kunt u controleren of alle waarden van set B in het bovenstaande resultaat staan ​​(wat betekent dat alle bereiken van B in ten minste één bereik van A zitten):

 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'
     ));

Om de kruising te krijgen, kun je beide oversteken en de lege uitsluiten:

 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);

Een probleem met deze benadering is dat je alleen onsamenhangende reeksen door verschillende tuples moet houden. Bereik [1,5] en [4,7] van een set mogen bijvoorbeeld alleen in een tuple met [1,7] staan. Om er zeker van te zijn, kun je ze invoegen in een tijdelijke tabel (tijdens het invoegen of bijwerken), ze kruisen de tabel zelf met tupels die elkaar overlappen en ze voegen zich bij die en houden de anderen zoals ze zijn.



  1. Wat betekent pooling=false in een MySQL-verbindingsreeks?

  2. Hoe de eerste letter van een record in SQL met een hoofdletter te schrijven

  3. MySQL waar NIET IN naam array?

  4. Spark-dataframe schrijven naar postgres-database