SQLite删除STK_CODE重复行:保留min列最小值对应行的方案
作为SQLite新手遇到这种重复数据清理的问题很正常,我给你两种可行的方案,一种是纯SQL操作(适合快速验证效果),另一种是结合C++代码的实现(适合集成到你的项目里):
方案一:纯SQL语句解决
因为你的表没有主键,直接删除重复行需要先定位出要保留的记录,这里推荐用临时表的方法,逻辑清晰不容易出错:
创建临时表,存储每个
STK_CODE对应min值最小的行
把原表中需要保留的行筛选出来存入临时表:CREATE TEMP TABLE temp_table AS SELECT t1.* FROM your_table t1 INNER JOIN ( SELECT STK_CODE, MIN(min) AS min_val FROM your_table GROUP BY STK_CODE ) t2 ON t1.STK_CODE = t2.STK_CODE AND t1.min = t2.min_val;👉 注意把
your_table替换成你实际的表名。清空原表
这一步会删除原表所有数据,所以操作前一定要备份数据库!DELETE FROM your_table;将临时表的数据导回原表
把筛选后的干净数据放回原表:INSERT INTO your_table SELECT * FROM temp_table;(可选)删除临时表
SQLite的临时表会在会话结束后自动销毁,也可以手动删除:DROP TABLE temp_table;
如果你用的SQLite版本≥3.33.0(可以通过sqlite3 --version命令查看),也可以用更简洁的WITH子句直接删除重复行,不用临时表:
WITH to_keep AS ( SELECT STK_CODE, MIN(min) AS min_val FROM your_table GROUP BY STK_CODE ) DELETE FROM your_table WHERE NOT EXISTS ( SELECT 1 FROM to_keep WHERE your_table.STK_CODE = to_keep.STK_CODE AND your_table.min = to_keep.min_val );
方案二:C++结合sqlite3库实现
如果你需要把这个逻辑集成到C++项目里,可以用sqlite3的C API来执行上述SQL语句,下面是完整的示例代码:
示例代码
#include <sqlite3.h> #include <stdio.h> // 清理重复行的函数 int removeDuplicateRows(sqlite3* db) { char* errMsg = nullptr; int rc; // 1. 创建临时表存储要保留的行 const char* createTempSql = R"( CREATE TEMP TABLE temp_table AS SELECT t1.* FROM your_table t1 INNER JOIN ( SELECT STK_CODE, MIN(min) AS min_val FROM your_table GROUP BY STK_CODE ) t2 ON t1.STK_CODE = t2.STK_CODE AND t1.min = t2.min_val; )"; rc = sqlite3_exec(db, createTempSql, nullptr, nullptr, &errMsg); if (rc != SQLITE_OK) { fprintf(stderr, "创建临时表失败: %s\n", errMsg); sqlite3_free(errMsg); return rc; } // 2. 清空原表 const char* deleteSql = "DELETE FROM your_table;"; rc = sqlite3_exec(db, deleteSql, nullptr, nullptr, &errMsg); if (rc != SQLITE_OK) { fprintf(stderr, "清空原表失败: %s\n", errMsg); sqlite3_free(errMsg); return rc; } // 3. 将临时表数据导回原表 const char* insertSql = "INSERT INTO your_table SELECT * FROM temp_table;"; rc = sqlite3_exec(db, insertSql, nullptr, nullptr, &errMsg); if (rc != SQLITE_OK) { fprintf(stderr, "导回数据失败: %s\n", errMsg); sqlite3_free(errMsg); return rc; } // 4. 可选:删除临时表 const char* dropTempSql = "DROP TABLE temp_table;"; rc = sqlite3_exec(db, dropTempSql, nullptr, nullptr, &errMsg); if (rc != SQLITE_OK) { fprintf(stderr, "删除临时表失败: %s\n", errMsg); sqlite3_free(errMsg); return rc; } printf("重复行清理完成!\n"); return SQLITE_OK; } int main() { sqlite3* db; // 打开数据库文件,替换成你的数据库路径 int rc = sqlite3_open("your_database.db", &db); if (rc != SQLITE_OK) { fprintf(stderr, "无法打开数据库: %s\n", sqlite3_errmsg(db)); sqlite3_close(db); return rc; } // 执行清理操作 rc = removeDuplicateRows(db); // 关闭数据库连接 sqlite3_close(db); return rc; }
编译与运行
编译时需要链接sqlite3库,比如用g++的命令:
g++ your_code.cpp -o clean_duplicates -lsqlite3
运行编译后的程序即可完成重复行清理。
重要注意事项
- 备份数据库!:所有涉及删除数据的操作都有风险,一定要先备份你的数据库文件,避免数据丢失。
- 替换占位符:把代码和SQL中的
your_table换成你实际的表名,your_database.db换成你的数据库文件路径。 - SQLite版本检查:如果想用WITH子句的方案,确保你的SQLite版本不低于3.33.0。
内容的提问来源于stack exchange,提问作者Hard work
相关产品推荐
相关产品推荐

