Możesz użyć typów danych zakresu i przechowywać każdy rozłączny typ w rzędzie.
Dla Twojej próbki:
-- 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]');
Aby sprawdzić, czy B jest podzbiorem A, możesz połączyć oba ze wszystkimi krotkami, których zakres A zawiera zakres B:
SELECT b.range
FROM sets b JOIN sets a
ON a.range @> b.range
WHERE a.id='A' AND b.id='B'
Dzięki temu możesz sprawdzić, czy wszystkie wartości ze zbioru B znajdują się w powyższym wyniku (co oznacza, że wszystkie zakresy B są zawarte w co najmniej jednym zakresie 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'
));
Aby uzyskać skrzyżowanie, możesz połączyć oba i wykluczyć puste:
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);
Jednym z problemów związanych z tym podejściem jest to, że musisz zachować tylko rozłączne zakresy S przez różne krotki. Na przykład zakres [1,5] i [4,7] ze zbioru musi znajdować się w krotce zawierającej tylko [1,7]. Aby się upewnić, możesz wstawić je do tabeli tymczasowej (podczas wstawiania lub aktualizowania), krzyżują się one z tabelą zachodzącymi na siebie krotkami, a następnie dołączają do nich i zachowują pozostałe takie, jakie są.