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数据库连接时关注竞争条件

限制输入 SQLite3 的字符数

SQLITE3:两个不相关的表与多行的联合

使用 sql.Open 进行 SQLite3 数据库连接

Python / Sqlite3:使用 GROUP_CONCAT 左连接

SQLite3数据库