选择列具有公共值的第n行/岛行?

时间:2017-03-07 08:48:02

标签: sqlite

我需要选择列中具有公共值的所有行(对于范围)。

例如(从最后一行开始)

我尝试选择_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

在我的尝试中,我使用Common Table Expressions_user_id的结果进行分组。这给出了包含唯一值的最后一行的索引(例如。SELECT _id FROM t1 GROUP BY _user_id LIMIT 2;将产生:[6,3])

然后我使用这两个值来选择LIMIT 1 OFFSET 1是低端(3)而LIMIT 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时,有没有办法生成能够生成这些输出的查询?:

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

谢谢!

1 个答案:

答案 0 :(得分:1)

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

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;