SQLite:从最后一行减去第一行

SQLite: Subtract 1st Row from Last Row

我有一个大的 table data,每行都有一个升序计数器 counter 列。假设我的程序运行正常,counter 应该每行增加 20 个单位。

因此,对于每个 table,如果程序正常运行,查询 Select (Max(counter)-Min(counter))/(Max(ROWID)-1) 应该 return 20。如果程序删除任何行,查询将 return > 20.

据我知道最大和最小值在第 0 行和第 N 行,有没有更好的方法来运行这个搜索而不需要处理器搜索整个table 最大值?

您可以做的是维护一个 table 单行记录最低值和最高值。

您可以使用 TRIGGER 维护此 table。

由于触发,每次插入、更新、删除都会有少量开销,但不会扫描 max/min,而是 min/max 值是根据 [=46] 行计算的=] 请注意,删除会使您的 每行增加 20 个单位。 作为可以应用的规则。

例如,考虑以下演示。注意它包含一个额外的(不必要的)触发器,允许监视触发:-

DROP TABLE IF EXISTS maintable;
DROP TABLE IF EXISTS counterlowhigh;
DROP TABLE IF EXISTS trigger_monitor; /*<<<<<<<<<< ONLY EXISTS TO MONITOR THE TRIGGERING - OTEHREWISE NOT NEEDED */

CREATE TABLE IF NOT EXISTS maintable (id INTEGER PRIMARY KEY, counter INTEGER, othercolumns TEXT);
CREATE TABLE IF NOT EXISTS counterlowhigh (id INTEGER PRIMARY KEY, low INTEGER, high INTEGER);
INSERT INTO counterlowhigh VALUES(1,0,0);
/* ONLY EXISTS TO MONITOR THE TRIGGERING - OTEHREWISE NOT NEEDED */
CREATE TABLE IF NOT EXISTS trigger_monitor (id INTEGER PRIMARY KEY, timestamp text DEFAULT CURRENT_TIMESTAMP, maintable_id INTEGER, operation TEXT);
CREATE TRIGGER IF NOT EXISTS maintain_counterlowhigh_afterinsert AFTER INSERT ON maintable 
    BEGIN 
        UPDATE counterlowhigh SET low = min(low,new.counter), high = max(high,new.counter) WHERE id = 1;
        /* ONLY EXISTS TO MONITOR THE TRIGGERING - OTEHREWISE NOT NEEDED */
        INSERT INTO trigger_monitor (maintable_id,operation) 
            VALUES (
            new.id,
            'AFTER INSERT counter was '||new.counter
            ||' High='||(SELECT high FROM counterlowhigh WHERE id=1)
            ||' Low='||(SELECT low FROM counterlowhigh WHERE id= 1)
            )
        ;
    END
;
CREATE TRIGGER IF NOT EXISTS maintain_counterlowhigh_afterupdate AFTER UPDATE ON maintable
    BEGIN
        UPDATE counterlowhigh SET low = min(low,new.counter), high = max(high,new.counter) WHERE id = 1;
        /* ONLY EXISTS TO MONITOR THE TRIGGERING - OTEHREWISE NOT NEEDED */
        INSERT INTO trigger_monitor (maintable_id,operation) 
            VALUES (
            new.id,
            'AFTER UPDATE counter was '||new.counter
            ||' High='||(SELECT high FROM counterlowhigh WHERE id=1)
            ||' Low='||(SELECT low FROM counterlowhigh WHERE id= 1)
            )
        ;
    END
;
CREATE TRIGGER IF NOT EXISTS maintain_counterlowhig_afterdelete AFTER DELETE ON maintable
    BEGIN
        UPDATE counterlowhigh SET low = old.counter + 20 WHERE low = old.counter;
        UPDATE counterlowhigh SET high = old.counter - 20 WHERE high = old.counter;
        /* ONLY EXISTS TO MONITOR THE TRIGGERING - OTEHREWISE NOT NEEDED */
        INSERT INTO trigger_monitor (maintable_id,operation) 
            VALUES (
            old.id,
            'AFTER DELETE counter was '||old.counter
            ||' High='||(SELECT high FROM counterlowhigh WHERE id=1)
            ||' Low='||(SELECT low FROM counterlowhigh WHERE id= 1)
            )
        ;
    END
;

/* Test insertion  */
WITH 
    cte(i) AS (SELECT 0 UNION ALL SELECT i+1 FROM cte LIMIT 10000)
INSERT INTO maintable (counter,othercolumns) SELECT i * 20,'other data '||i FROM cte
;
/* Show counterhighlow data after insertions */
SELECT * FROM counterlowhigh;
/* Test some deletions */
DELETE FROM maintable WHERE id = 1;
DELETE FROM maintable WHERE id IN (1 /*<<<<< already deleted by previous delete */,53,73,10000,10001) OR id > 10000 /*<<<< should not do anything */;
/* Show counterhighlow data after insertions */
SELECT * FROM counterlowhigh;

所以最初 counterhighlow table 的低点和高点都为 0。 在 10000 次插入后 counterhighlow 是:-

删除后(最低行和最高行被包含在删除中)然后 counterhighlow 是:-

触发器监控 table 包括 10004 行,前 10000 行用于插入,例如:-

.....

最后 4 行,删除为:-