【问题标题】:Sqlite datetime hour differenceSqlite 日期时间时差
【发布时间】:2018-04-16 19:53:07
【问题描述】:

如何使用 Python Sqlite sqlite3 模块获取日期时间列相差

我试过了:

import sqlite3, datetime
db = sqlite3.connect(':memory:', detect_types=sqlite3.PARSE_DECLTYPES)

c = db.cursor()
c.execute('CREATE TABLE mytable (id integer, date timestamp)')
c.execute('INSERT INTO mytable VALUES (1, ?)', (datetime.datetime(2018,1,1,23,0),))
c.execute('INSERT INTO mytable VALUES (2, ?)', (datetime.datetime(2018,1,2,0,0),))
c.execute('INSERT INTO mytable VALUES (3, ?)', (datetime.datetime(2018,1,9,0,0),))

此查询有效:

c.execute('SELECT mt1.date, mt2.date FROM mytable mt1, mytable mt2')

然后返回:

(datetime.datetime(2018, 1, 1, 23, 0), datetime.datetime(2018, 1, 1, 23, 0))
(datetime.datetime(2018, 1, 1, 23, 0), datetime.datetime(2018, 1, 2, 0, 0))
(datetime.datetime(2018, 1, 1, 23, 0), datetime.datetime(2018, 1, 9, 0, 0))
...
(datetime.datetime(2018, 1, 9, 0, 0), datetime.datetime(2018, 1, 9, 0, 0))

datetime 差异计算不起作用:

c.execute('SELECT ABS(mt1.date - mt2.date) FROM mytable mt1, mytable mt2')

(0,)
(0,)
...

所以最终不可能使用带有WHERE ABS(mt1.date - mt2.date) < 2 的查询来过滤最大日期时间差 2 小时。

怎么做?

注意:

  • detect_types=sqlite3.PARSE_DECLTYPES 确保查询返回一个datetype Python 对象,这是有效的。

  • 这可以测试两个日期时间是否是同一天,这要归功于DATE 函数:

    SELECT mt1.*, mt2.* FROM mytable mt1, mytable mt2 WHERE DATE(mt1.date) = DATE(mt2.date)
    

【问题讨论】:

  • c.execute('SELECT (mt1.date - mt2.date) FROM mytable mt1, mytable mt2') 返回什么(没有ABS)? `
  • @pault 它也返回0
  • @Basj:这是因为将 SQLite 日期/时间字符串转换为数值只会给出年份,即表中所有行的年份为 2018(因此差异为 0)。正如您已经发现的那样,您需要使用JULIANDAY 函数来获得有意义的答案。
  • 谢谢@dan04。好奇:是否有一个 Unix 时间戳函数可以允许 ABS(UNIXTIMESTAMP(mt1.date) - UNIXTIMESTAMP(mt2.date)) < 7200
  • @Basj:是的,拼写为STRFTIME('%s', the_date)

标签: python datetime sqlite


【解决方案1】:

这要归功于JULIANDAY,它允许将日期时间差计算为浮点数:

SELECT ABS(JULIANDAY(mt1.date) - JULIANDAY(mt2.date)) FROM mytable mt1, mytable mt2

所以 2 小时的差异可以转化为这种情况:

ABS(JULIANDAY(mt1.date) - JULIANDAY(mt2.date)) < 0.083333

因为 2 小时/24 小时 = 1/12 ~ 0.083333


这个查询也可以:

SELECT ABS(STRFTIME("%s", mt1.date) - STRFTIME("%s", mt2.date)) FROM mytable mt1, mytable mt2

2 小时的条件是:

ABS(STRFTIME("%s", mt1.date) - STRFTIME("%s", mt2.date)) < 7200

即最大差异 7200 秒(STRFTIME("%s", mt1.date) 给出 Unix 时间戳)。

【讨论】:

  • FWIW, ABS(STRFTIME("%s", mt1.date) - STRFTIME("%s", mt2.date)) &lt; 7200 似乎比 JULIANDAY 条件慢一点。有谁知道如何优化这些查询?
  • 旁注:这是一种大幅提高查询性能的方法(提高 50 倍):stackoverflow.com/q/49887709/1422096
猜你喜欢
  • 2021-12-23
  • 2021-02-12
  • 2015-12-16
  • 1970-01-01
  • 1970-01-01
  • 2021-08-17
  • 2016-06-24
相关资源
最近更新 更多