Sqlite 选择列具有公共值的第n个范围/行孤岛?

Sqlite 选择列具有公共值的第n个范围/行孤岛?,sqlite,Sqlite,我需要为一个范围选择所有行,这些行在一列中有一个公共值 例如,从最后一行开始 我尝试选择_user_id==1的所有行,直到_user_id!=1号 在这种情况下,会导致选择行[4、5、6] +------------------------+ | _id _user_id amount | +------------------------+ | 1 1 777 | | 2 2 1 | | 3 2 1

我需要为一个范围选择所有行,这些行在一列中有一个公共值

例如,从最后一行开始

我尝试选择_user_id==1的所有行,直到_user_id!=1号

在这种情况下,会导致选择行[4、5、6]

+------------------------+
| _id  _user_id   amount |
+------------------------+
| 1    1          777    |
| 2    2          1      |
| 3    2          11     |
| 4    1          10     |
| 5    1          100    |
| 6    1          101    |
+------------------------+

/*Create the table*/
CREATE TABLE IF NOT EXISTS t1 ( 
_id              INTEGER           PRIMARY KEY AUTOINCREMENT,
_user_id         INTEGER,
amount           INTEGER);

/*Add the datas*/
INSERT INTO t1 VALUES(1, 1, 777);
INSERT INTO t1 VALUES(2, 2, 1);
INSERT INTO t1 VALUES(3, 2, 11);
INSERT INTO t1 VALUES(4, 1, 10);
INSERT INTO t1 VALUES(5, 1, 100);
INSERT INTO t1 VALUES(6, 1, 101);

/*Check the datas*/
SELECT * FROM t1;

1|1|777
2|2|1
3|2|11
4|1|10
5|1|100
6|1|101
在我的尝试中,我使用对_user_id的结果进行分组。这将给出最后一行的索引,其中包含唯一值,例如,按_user_id LIMIT 2从t1 group中选择_id;将产生:[6,3]

然后,我使用这两个值选择一个范围,其中极限1偏移量1是下限3,极限1是上限6

WITH test AS (
    SELECT _id FROM t1 GROUP BY _user_id LIMIT 2
) SELECT * FROM t1 WHERE _id BETWEEN 1+ (
    SELECT * FROM test LIMIT 1 OFFSET 1
) and (
    SELECT * FROM test LIMIT 1
); 
输出:

4|1|10
5|1|100
6|1|101
这在选择最后一个岛时似乎可以,但我真正需要的是选择第n个岛的方法

当提供参数n时,是否有一种方法可以生成能够生成类似这些输出的查询


谢谢

SQL表是无序的,因此搜索孤岛的唯一方法是搜索连续的_id值:


谢谢你提供这个!然而,我遇到了一些问题,如果我删除一行,它将停止在前一行,因为主键不再是连续的。有什么想法吗?——“发牢骚”——这不是最初的问题所要求的……非常抱歉没有在前面提到这一点。无论如何,我已经找到了一种解决方法,通过更好地管理我如何删除条目,并确保PK保持连续,尽管这在将来可能仍然是一个问题。但是非常感谢你的回答,它非常有帮助!更改PKs通常是一个更糟糕的主意。谢谢您更新您的答案。它工作得非常好!是的,我同意改变PKs,我现在把代码撕掉。
island (n=1): 
   4|1|10
   5|1|100
   6|1|101

island (n=2): 
   2|2|1
   3|2|11

island (n=3): 
   1|1|777
WITH RECURSIVE t1_with_islands(_id, _user_id, amount, island_number) AS (
  SELECT _id,
         _user_id,
         amount,
         1
  FROM t1
  WHERE _id = (SELECT max(_id)
               FROM t1)

  UNION ALL

  SELECT t1._id,
         t1._user_id,
         t1.amount,
         CASE WHEN t1._user_id = t1_with_islands._user_id
              THEN island_number
              ELSE island_number + 1
         END
  FROM t1
  JOIN t1_with_islands ON t1._id = (SELECT max(_id)
                                    FROM t1
                                    WHERE _id < t1_with_islands._id)
)
SELECT *
FROM t1_with_islands
ORDER BY _id;