SQLite3 使用时间限制内部连接
Posted
技术标签:
【中文标题】SQLite3 使用时间限制内部连接【英文标题】:SQLite3 Limiting Inner Join Using Time 【发布时间】:2014-05-17 03:58:48 【问题描述】:我正在尝试使用 SQLite3 在具有相似数据的两个表之间形成相关性。 这是我目前所拥有的:
CREATE TABLE a (date TEXT, user TEXT, ip TEXT);
CREATE INDEX a_index ON a (date, user, ip);
CREATE TABLE b (date TEXT, ip TEXT);
CREATE UNIQUE INDEX b_index ON b (date, ip);
INSERT INTO a VALUES('2014-03-01 03:15:16', 'a', '127.0.0.1');
INSERT INTO a VALUES('2014-03-01 03:15:18', 'b', '127.0.0.2');
INSERT INTO a VALUES('2014-03-01 03:15:21', 'c', '127.0.0.3');
INSERT INTO a VALUES('2014-03-01 03:15:21', 'd', '127.0.0.4');
INSERT INTO a VALUES('2014-03-01 03:15:29', 'e', '127.0.0.5');
INSERT INTO a VALUES('2014-03-01 03:16:32', 'f', '127.0.0.6');
INSERT INTO b VALUES('2014-03-01 03:15:16', '127.0.0.1');
INSERT INTO b VALUES('2014-03-01 03:15:17', '127.0.0.1');
INSERT INTO b VALUES('2014-03-01 03:15:19', '127.0.0.1');
INSERT INTO b VALUES('2014-03-01 03:15:22', '127.0.0.4');
INSERT INTO b VALUES('2014-03-01 03:16:32', '127.0.0.5');
我知道我可以简单地使用内部连接来组合这两个集合,如下所示:
SELECT *
FROM a
JOIN b ON a.ip = b.ip AND a.date = b.date;
它会返回
2014-03-01 03:15:16|a|127.0.0.1|2014-03-01 03:15:16|127.0.0.1
正如预期的那样。但是,由于时间记录的时钟漂移。我想匹配任何可能的条目 +- 3 秒。在这种情况下,我使用了:
SELECT *
FROM a
JOIN b ON a.ip = b.ip AND a.date BETWEEN DATETIME(b.date, '-3 seconds') AND DATETIME(b.date, '+3 seconds');
这很有效,尽管它返回的条目比我想要的多。而不是以下内容:
2014-03-01 03:15:16|a|127.0.0.1|2014-03-01 03:15:16|127.0.0.1
2014-03-01 03:15:16|a|127.0.0.1|2014-03-01 03:15:17|127.0.0.1
2014-03-01 03:15:16|a|127.0.0.1|2014-03-01 03:15:19|127.0.0.1
2014-03-01 03:15:21|d|127.0.0.4|2014-03-01 03:15:22|127.0.0.4
我想知道如果在 b 表中找到匹配的条目,是否可以在 a 表中每个条目最多只返回一个条目。所以预期的结果应该是这样的:
2014-03-01 03:15:16|a|127.0.0.1|2014-03-01 03:15:16|127.0.0.1
2014-03-01 03:15:21|d|127.0.0.4|2014-03-01 03:15:22|127.0.0.4
应该/如何做到这一点?
【问题讨论】:
你得到的结果集似乎是正确的。您为127.0.0.1
ip 选择2014-03-01 03:15:16
而不是2014-03-01 03:15:18
的逻辑是什么?
好问题,但我实际上是在选择出现的第一个条目,类似于 SQL 中的 LIMIT 1。据说,我想要最接近“a”表中的时间。
当两个表中有多个可能的匹配项时会发生什么?
所以基本上我正在寻找类似于以下逻辑:a)循环遍历表A的条目; b) 查看表 B 中是否有对应的条目具有相同的 IP 且时间戳为 += 3 秒; c) 如果存在一个条目,则打印该条目。如果存在多个条目,则选择与表 A 中的条目最接近的条目并打印; d) 继续表 A 中的下一个条目。
明确SELECT
您想要的字段,省略第二个时间戳(无论如何您似乎都不感兴趣),这使得“重复”行不同,并使用SELECT DISTINCT
所以你只会得到唯一的行。
【参考方案1】:
我的评论,上面(“显式选择您想要的字段,忽略第二个时间戳(无论如何您似乎都不感兴趣),这使得“重复”行不同,并使用 SELECT DISTINCT 所以您只能获得唯一的行。”),您可以尝试以下操作:
SELECT DISTINCT a.date, a.user, a.ip
FROM a JOIN b ON a.ip = b.ip
AND a.date
BETWEEN DATETIME(b.date, '-3 seconds')
AND DATETIME(b.date, '+3 seconds');
【讨论】:
有趣的方法,将看看这个,看看它是否适用于我正在做的事情,谢谢!以上是关于SQLite3 使用时间限制内部连接的主要内容,如果未能解决你的问题,请参考以下文章
访问在QThread内部由Pynput侦听器调用的线程中访问的SQLite3数据库连接时关注竞争条件