首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SQLite删除包含group的多行并连接两个表

SQLite删除包含group的多行并连接两个表
EN

Stack Overflow用户
提问于 2018-06-12 11:32:56
回答 1查看 858关注 0票数 0

我有两张桌子。第一个是聊天室表,包含当前用户与朋友的消息。第二个表是线程,它保存线程聊天(用户与朋友的线程聊天-包含多条消息)

我想要的是:线程聊天1我想删除x消息,线程聊天2删除y消息,线程3删除z消息.

如何在一个sql查询中实现它?

每一表列如下:

表聊天: msgId、threadId、消息、时间戳。

表线程: threadId,displayName。

EN

回答 1

Stack Overflow用户

发布于 2018-06-12 14:22:01

通过临时表存储要保存多少记录。

并通过一个技巧来模拟带有分区的ROW_NUMBER。

安装示例数据:

代码语言:javascript
复制
drop table IF EXISTS TestThreads;
create Table TestThreads (threadId INTEGER NOT NULL primary key, displayName TEXT);
drop table IF EXISTS TestChats;
create Table TestChats (msgId INTEGER NOT NULL primary key AUTOINCREMENT, threadId INTEGER, "timestamp" DATETIME, messages TEXT);

--
-- Sample Data
--
delete from TestThreads;
insert into TestThreads (threadId, displayName) values
 (1,'Superman')
,(2,'Son Goku')
,(3,'Bai Xiaochun')
;

delete from TestChats;
insert into TestChats (threadId, "timestamp", messages) values 
 (1,'2018-01-01 11:15:01','It is not')
,(1,'2018-01-01 11:15:02','an S')
,(1,'2018-01-01 11:15:03','on my world')
,(1,'2018-01-01 11:15:04','it means hope')
,(2,'2018-01-01 12:15:01','Kame')
,(2,'2018-01-01 12:15:02','Hame')
,(2,'2018-01-01 12:15:03','Hhhaaa')
,(2,'2018-01-01 12:15:04','aaaaaaaaaaaaaaaa')
,(3,'2018-01-01 13:15:01','When')
,(3,'2018-01-01 13:15:02','I start deleting')
,(3,'2018-01-01 13:15:03','I frighten')
,(3,'2018-01-01 13:15:04','even myself')
 ;

将带有数字的线程in放在一个临时表中:

代码语言:javascript
复制
--
-- create and fill temporary table
--
DROP TABLE IF EXISTS _tmpThreadsToCleanup;
CREATE TEMP TABLE _tmpThreadsToCleanup(threadId int primary key, NrToDel int);

DELETE FROM _tmpThreadsToCleanup;
INSERT INTO _tmpThreadsToCleanup(threadId, NrToDel)
SELECT threadId, 3 as NrToDel from TestThreads where displayName = 'Superman' UNION ALL
SELECT threadId, 2 as NrToDel from TestThreads where displayName = 'Son Goku' UNION ALL
SELECT threadId, 1 as NrToDel from TestThreads where displayName = 'Bai Xiaochun'
;

删除:

代码语言:javascript
复制
--
-- Delete messages based on the counts in the temporary table
--
DELETE 
FROM TestChats
WHERE msgId IN (
   SELECT c.msgId
    FROM TestChats AS c
    JOIN _tmpThreadsToCleanup AS r on (r.threadId = c.threadId)
    WHERE (select count(*) from TestChats c2 WHERE c2.threadId = c.threadId AND c2.msgID <= c.msgId) <= r.NrToDel
);

查询剩余的内容:

代码语言:javascript
复制
SELECT th.threadId, th.displayName, ch.msgId, ch."timestamp", ch.messages
FROM TestThreads AS th
LEFT JOIN TestChats AS ch on (ch.threadId = th.threadId)
ORDER BY th.threadId, ch.msgId;

结果:

代码语言:javascript
复制
threadId displayName msgId timestamp           messages
-------- ----------- ----- ------------------- ------------
1        Superman      4   2018-01-01 11:15:04 it means hope
2        Son Goku      7   2018-01-01 12:15:03 Hhhaaa
2        Son Goku      8   2018-01-01 12:15:04 aaaaaaaaaaaaaaaa
3        Bai Xiaochun 10   2018-01-01 13:15:02 I start deleting
3        Bai Xiaochun 11   2018-01-01 13:15:03 I frighten
3        Bai Xiaochun 12   2018-01-01 13:15:04 even myself

备注:

因此,为了模拟ROW_NUMBER,在每条记录上进行计数(*)上的连接,该方法应该是相当慢的。

但是,如果要删除的记录数量与所选线程相同,则可以使用限制。

代码语言:javascript
复制
DELETE 
FROM TestChats 
WHERE msgId IN (
   SELECT c.msgId
    FROM TestChats AS c
    JOIN _tmpThreadsToCleanup AS r on (r.threadId = c.threadId)
    WHERE c.threadId = TestChats.threadId
    ORDER BY c.msgID ASC
    LIMIT 2 -- Fixed number
);

如果您想做相反的事情,并保留N条记录,那么可以使用带有偏移量的限制。那么顺序应该是下降的。

这样做的好处是,这样的查询在第二次运行时不会删除额外的记录。

代码语言:javascript
复制
DELETE
FROM TestChats 
WHERE msgId IN (
   SELECT c.msgId
    FROM TestChats AS c
    JOIN _tmpThreadsToCleanup AS r on (r.threadId = c.threadId)
    WHERE c.threadId = TestChats.threadId
    ORDER BY c.msgID DESC
    LIMIT -1 OFFSET 2 -- Fixed number
);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50816119

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档