sql >> Databasteknik >  >> RDS >> PostgreSQL

Lagra och fråga efter intervallträd i PostgreSQL

Du kan använda intervalldatatyperna och lagra varje osammanhängande typ i en rad.

För ditt exempel:

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

För att kontrollera om B är en delmängd av A, kan du slå samman båda med alla tupler som A:s intervall innehåller B:s intervall:

 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 kontrollera om alla värden från uppsättning B är i ovanstående resultat (vilket kommer att innebära att alla områden för B finns i minst ett område av 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'
     ));

För att få korsningen kan du korsansluta båda och exkludera de tomma:

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

Ett problem med det här tillvägagångssättet är att du endast måste hålla disjunkta rangeS genom olika tupler. Till exempel, intervall [1,5] och [4,7] från en uppsättning måste ligga i en tupel med endast [1,7]. För att vara säker på det kan du infoga dem i en tillfällig tabell (medan du infogar eller uppdaterar), de korsar sammanfogar själva tabellen med tuplar som överlappar och de sammanfogar dem och behåller de andra som de är.



  1. Oracle:hur får man procent av totalt genom en fråga?

  2. Hur man kontrollerar NULL eller ogiltig i HQL-fråga

  3. Är det säkert att ändra ordning på kolumner i schema.rb för Rails 4/Postgres?

  4. hur laddar man ner blobbaserad fil från MySQL-databas i PHP?