【问题标题】:How to know the current row is the last one in SQlite?如何知道当前行是 SQlite 中的最后一行?
【发布时间】:2019-05-10 09:18:34
【问题描述】:

我正在使用 Sqlite 3。

在调用 sqlite3_step() 之前,我需要知道当前行是否是 SQL 查询结果中的最后一行。

检查现有帖子后

SQLite3 - how to know if the current row is the last row

How to check if the current row is the last selected row in a sql query?

由于SQlite3中的每一行都有一个ROWID,我想办法写代码,如下:

SELECT (ROWID = MAX(ROWID)) AS IsLast FROM MyTable ORDER BY ROWID;

MyTable 中的数据是:

|BID|
|3|
|2|
|5|
|7|

预期的结果是除了最后一行之外的所有行都是FALSE,如下:

    |0|
    |0|
    |0|
    |1|

但实际结果是:

|1|

此外,我尝试将代码集成到更复杂的查询中,查询来自SQL select only rows with max value on a column,如下所示:

SELECT a.id, a.rev, a.contents, b.mycount, (a.ROWID = MAX(a.ROWID)) AS IsLast
FROM YourTable a
INNER JOIN (
    SELECT id, MAX(rev) rev, COUNT(id) mycount
    FROM YourTable
    GROUP BY id
) b ON a.id = b.id AND a.rev = b.rev ORDER BY a.ROWID;

以原帖中的原表为例:

        +------+-------+--------------------------------------+
        | id   | rev   | content                              |
        +------+-------+--------------------------------------+
        | 1    | 1     | ...                                  |
        | 2    | 1     | ...                                  |
        | 1    | 2     | ...                                  |
        | 1    | 3     | ...                                  |
        +------+-------+--------------------------------------+

使用查询后,预期的结果应该是(最后一列是IsLast标志):

    |2|1|...|1|0|
    |1|3|...|3|1|

但实际结果只有一行:

|1|3|...|3|1|

有什么问题?

谢谢

【问题讨论】:

标签: sql sqlite


【解决方案1】:

由您的子查询引起的错误不包含ROWID 列,但您在主查询中使用了此列。

您可以尝试使用子查询获取MAX(ROWID),然后使用CASE WHEN 设置最后一个标志。

您的第一个查询

架构 (SQLite v3.18)

CREATE TABLE YourTable(
  BID int
);

INSERT INTO YourTable VALUES (3);
INSERT INTO YourTable VALUES (2);
INSERT INTO YourTable VALUES (5);
INSERT INTO YourTable VALUES (7);

查询 #1

SELECT  
     BID,(CASE WHEN (SELECT MAX(ROWID) FROM YourTable) = a.ROWID then 1 else 0 end) AS IsLast
FROM YourTable a;

| BID | IsLast |
| --- | ------ |
| 3   | 0      |
| 2   | 0      |
| 5   | 0      |
| 7   | 1      |

View on DB Fiddle

架构 (SQLite v3.18)

CREATE TABLE YourTable(
  Id int,
  rev int,
  contents varchar(50)
);

INSERT INTO YourTable VALUES (1,1,'test1');
INSERT INTO YourTable VALUES (2,1,'test2');
INSERT INTO YourTable VALUES (1,2,'test1');
INSERT INTO YourTable VALUES (1,3,'test2');

查询 #1

SELECT a.*,
       (CASE WHEN maxROWID = a.ROWID then 1 else 0 end) AS IsLast
FROM YourTable a
 JOIN 
(
  SELECT Id,
         MAX(rev) rev, 
         COUNT(id) mycount,
         (SELECT MAX(ROWID) FROM YourTable) maxROWID
  FROM YourTable
  group by Id
) b  ON a.id = b.id AND a.rev = b.rev
ORDER BY a.ROWID;

| Id  | rev | contents | IsLast |
| --- | --- | -------- | ------ |
| 2   | 1   | test2    | 0      |
| 1   | 3   | test2    | 1      |

View on DB Fiddle

【讨论】:

  • @alancc 我看到你编辑了你的问题我编辑了我的答案你可以试试。
  • 对于 query1,它可以工作。但是,当我尝试将其简化为: SELECT BID,(CASE WHEN MAX(ROWID) = a.ROWID then 1 else 0 end) AS IsLast FROM YourTable a;那我又要失败了。我不明白为什么我必须使用子查询来获取 ROWID 的最大值?
  • 对于查询2,(SELECT MAX(ROWID) FROM YourTable) maxROWID 可能返回一个ROWID,其对应的行可能不在最终结果集中,从而导致所有IsLast 变为0?
  • @alancc 子查询可以获取表中id的MAX,然后与它进行比较以检查最后一行
【解决方案2】:

文档说 sqlite3_step() 根据查询的状态返回不同的值

https://www.sqlite.org/c3ref/step.html

乍一看,您应该调用它,直到它返回 SQLITE_DONE。然后,您需要重置它,然后才能在该语句上再次调用它

【讨论】:

  • 是的,但是当我得到 SQLITE_ROW 而不是 SQLITE_DONE 时,我不知道是否有下一行,直到我再次调用 sqlite3_step 并得到 SQLITE_DONE。在这样做之前我想知道。
  • 为什么?只需调用它并完成,然后停止。如果您此时需要访问上一行,请在循环时保留对上一行数据的引用。 IE。当您完成时,您会突然知道最近读取的数据将是最后一行,因此请安排您的代码,以免覆盖/丢失它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-13
  • 1970-01-01
  • 1970-01-01
  • 2014-08-25
  • 1970-01-01
  • 2020-11-11
相关资源
最近更新 更多