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.