Я понимаю, что sqlite не поддерживает аналитические функции, но ... Вот потенциальное решение SQL, которое использует аналитические функции.Я запустил это в Postgresql.
CREATE TABLE test(id VARCHAR(16), date1 DATE, date2 DATE);
INSERT INTO test VALUES('foo', '2011-01-01', '2011-01-15');
INSERT INTO test VALUES('bar', '2011-01-02', '2011-01-04');
INSERT INTO test VALUES('bar', '2011-01-05', '2011-01-10'); -- not contiguous
INSERT INTO test VALUES('foo', '2011-01-25', '2011-01-30');
INSERT INTO test VALUES('foo', '2011-01-15', '2011-01-18'); -- contiguous
INSERT INTO test VALUES('foo', '2011-01-28', '2011-01-31'); -- overlap
INSERT INTO test VALUES('bar', '2011-01-07', '2011-01-08'); -- subset chopped
postgres=# SELECT * FROM test ORDER BY id, date1;
id | date1 | date2
-----+------------+------------
bar | 2011-01-02 | 2011-01-04
bar | 2011-01-05 | 2011-01-10
bar | 2011-01-07 | 2011-01-08
foo | 2011-01-01 | 2011-01-15
foo | 2011-01-15 | 2011-01-18
foo | 2011-01-25 | 2011-01-30
foo | 2011-01-28 | 2011-01-31
(7 rows)
SELECT id
,MIN(date1) AS date1
,MAX(date2) AS date2
FROM ( SELECT id, date1, date2, previous_date1, previous_date2
,SUM( CASE WHEN date1 > previous_date2 THEN 1 ELSE 0 END ) OVER(PARTITION BY id ORDER BY id, date1) AS group_id
FROM ( SELECT id, date1, date2
,COALESCE( LAG(date1) OVER (PARTITION BY id ORDER BY id, date1), date1 ) previous_date1
,COALESCE( LAG(date2) OVER (PARTITION BY id ORDER BY id, date1), date2 ) previous_date2
FROM test
ORDER BY id, date1, date2
) AS x
) AS y
GROUP BY id, group_id
ORDER BY 1,2;
id | date1 | date2
-----+------------+------------
bar | 2011-01-02 | 2011-01-04
bar | 2011-01-05 | 2011-01-10
foo | 2011-01-01 | 2011-01-18
foo | 2011-01-25 | 2011-01-31
(4 rows)
ОБЪЯСНЕНИЕ
Работая изнутри, сначала отсортируйте строки по идентификатору и дате, и добавьте два дополнительных столбца в каждую строку, чтобы указать предыдущую строкузначения date1 и date2.
id | date1 | date2 | previous_date1 | previous_date2
-----+------------+------------+----------------+----------------
bar | 2011-01-02 | 2011-01-04 | 2011-01-02 | 2011-01-04
bar | 2011-01-05 | 2011-01-10 | 2011-01-02 | 2011-01-04
bar | 2011-01-07 | 2011-01-08 | 2011-01-05 | 2011-01-10
foo | 2011-01-01 | 2011-01-15 | 2011-01-01 | 2011-01-15
foo | 2011-01-15 | 2011-01-18 | 2011-01-01 | 2011-01-15
foo | 2011-01-25 | 2011-01-30 | 2011-01-15 | 2011-01-18
foo | 2011-01-28 | 2011-01-31 | 2011-01-25 | 2011-01-30
(7 rows)
Затем пометьте каждую строку, имеющую перекрытие (между date1 и previous_date1), суммируя эти флаги в группе «id», мы получим подгруппу идентификаторов.
id | date1 | date2 | previous_date1 | previous_date2 | flag | group_id
-----+------------+------------+----------------+----------------+------+----------
bar | 2011-01-02 | 2011-01-04 | 2011-01-02 | 2011-01-04 | 0 | 0
bar | 2011-01-05 | 2011-01-10 | 2011-01-02 | 2011-01-04 | 1 | 1
bar | 2011-01-07 | 2011-01-08 | 2011-01-05 | 2011-01-10 | 0 | 1
foo | 2011-01-01 | 2011-01-15 | 2011-01-01 | 2011-01-15 | 0 | 0
foo | 2011-01-15 | 2011-01-18 | 2011-01-01 | 2011-01-15 | 0 | 0
foo | 2011-01-25 | 2011-01-30 | 2011-01-15 | 2011-01-18 | 1 | 1
foo | 2011-01-28 | 2011-01-31 | 2011-01-25 | 2011-01-30 | 0 | 1
(7 rows)
Теперь мы можем группировать по идентификатору и сгенерированному «group_id».
Может быть, это безумие.Я не уверен, что на самом деле хотел бы использовать такого рода решения, потому что может быть сложно тестировать, проверять, документировать, и , особенно , выдержать несколько лет спустя.Но я все еще думаю, что это просто, что можно сделать с помощью sql.