删除某些数据后,如何从SQLITE3表中获取前 10 个和后 10 个不同的group_ids

How to get the previous 10 and next 10 distinct group_ids from a SQLITE3 table after some data have been removed

提问人:Sun Bear 提问时间:9/18/2023 最后编辑:Sun Bear 更新时间:9/19/2023 访问量:43

问:

从 sqlite3 表列中,我想在删除一些数据后以给定的偏移量提取前 10 个不同的值。

下面是一个示例脚本。

示例脚本:

import sqlite3
import random
from itertools import count
from typing import Literal

class Data:

    def __init__(self):
        self.con = sqlite3.connect("data.db",
                                   detect_types=sqlite3.PARSE_DECLTYPES,
                                   )
        self.cur = self.con.cursor()
        self.create_table()

    def create_table(self):
        table = """CREATE TABLE IF NOT EXISTS
        datatable(
            sn INTEGER,
            item_id TEXT PRIMARY KEY,
            group_id TEXT)
        """
        self.cur.execute("""DROP TABLE IF EXISTS datatable""")
        self.cur.execute(table)
        self.con.commit()

    def insert_data_row(self, data):
        sql = """INSERT OR IGNORE INTO datatable VALUES (?,?,?)"""
        self.cur.execute(sql, data)
        self.con.commit()


    def close(self):
        # 5. Close cursor & connection
        self.cur.close()
        self.con.close()

    def delete_group_id(self, group_id: str):
        sql = """DELETE FROM datatable WHERE group_id in (?)"""
        self.cur.execute(sql, (group_id,))
        self.con.commit()

    def get_previous_page_of_group_ids(self, group_id: str, span: int):
        sql1 = """SELECT MIN(sn) FROM 
                (SELECT sn from datatable WHERE group_id == (?))"""
        sql2 = """SELECT DISTINCT group_id FROM datatable 
                    WHERE sn < (?) ORDER BY group_id DESC LIMIT (?)     
                    OFFSET (?)"""
        self.cur.execute(sql1, (group_id,))
        start_sn = self.cur.fetchone()[0]
        print(f"{start_sn=}")
        self.cur.execute(sql2, (start_sn, span, 10))
        return self.cur.fetchall()

    def get_next_page_of_group_ids(self, group_id: str, span: int):
        sql1 = """SELECT MAX(sn) FROM 
                (SELECT sn from datatable WHERE group_id == (?))"""
        sql2 = """SELECT DISTINCT group_id FROM datatable
                    WHERE sn > (?) LIMIT (?)"""
        self.cur.execute(sql1, (group_id,))
        start_sn = self.cur.fetchone()[0]
        print(f"{start_sn=}")
        self.cur.execute(sql2, (start_sn, span,))
        return self.cur.fetchall()



if __name__ == "__main__":
    db = Data()
    db.create_table()
    counter = count()
    for i in range(50):
        repeats = random.randint(0, 5)
        for r in range(repeats):
            sn = next(counter)
            gid = f"G{i}"
            id = f"{gid}_F{r}"
            print(f"{sn=} {gid=} {id}")
            db.insert_data_row((sn, id, gid))
    start_gid = "G30"
    db.delete_group_id("G0")
    db.delete_group_id("G1")
    db.delete_group_id("G29")
    db.delete_group_id("G28")
    print(f"{start_gid=}")
    pb = db.get_previous_page_of_group_ids(start_gid, 10)
    print(f"{pb=}")
    nb = db.get_next_page_of_group_ids(start_gid, 10)
    print(f"{nb=}")
    db.close()

返回的答案是:

start_gid='G30'
start_sn=68
pb=[('G21',), ('G2',), ('G17',), ('G16',), ('G14',), ('G12',), ('G11',), ('G10',)]
start_sn=68
nb=[('G31',), ('G33',), ('G34',), ('G35',), ('G36',), ('G40',), ('G41',), ('G42',), ('G43',), ('G45',)]

pb并且似乎错了。它应该来自 和 。我无法弄清楚和方法中的错误。感谢您帮助理解此方法中的错误。谢谢。np((G27'),... to ..., (G18')((G31'),... to ..., (G40').get_previous_page_of_group_ids().get_next_page_of_group_ids()

更新:

我使用 SQLITE3 和 Python 命令的组合进行了重写。我可以知道编写此方法的纯SQLITE3方法吗?.get_previous_page_of_group_ids()

   def get_previous_page_of_group_ids(self, group_id: str, span: int):
        sql1 = """SELECT MIN(sn) FROM 
                (SELECT sn from datatable WHERE group_id == (?))"""
        sql2 = """SELECT group_id from datatable 
                WHERE sn < (?)"""
        self.cur.execute(sql1, (group_id,))
        start_sn = self.cur.fetchone()[0]
        print(f"{start_sn=}")
        self.cur.execute(sql2, (start_sn,))
        indexes = {int(i[0][1:]) for i in self.cur.fetchall()}
        print(f"{indexes=}")
        gids = [f"G{i}" for i in sorted(indexes, reverse=True)[:span]]
        gids.reverse()
        print(f"{gids=}")
        return gids

我还发现了一个问题,其中有时会导致方法和的结果出现错误。本声明__main__.get_next_page_of_group_ids().get_previous_page_of_group_ids()

repeats = random.randint(0, 5)

应该改为

repeats = random.randint(1, 5)
python sqlite sqlite3-python

评论

0赞 AKX 9/18/2023
if type in "previous":而且没有意义。该代码不会被执行。if type in "next":
0赞 Sun Bear 9/18/2023
@AKX 但是代码执行并返回了答案。为了避免与 python 命令混淆,我将其替换为 .type btype

答: 暂无答案