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 行,删除为:-
我有一个大的 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 行,删除为:-