需要使用 SQLite 查询进行一些奇怪的时间转换

问题描述 投票:0回答:1

我有一个 SQLite 数据库,包含列

time
name
value

time
列存储以秒为单位的纪元,例如“1695765399”,并且每隔一秒记录一次。

将有一个预定的触发器在 NZST 12:05(午夜)+5 分钟运行此查询,以便为 SQLite 数据库提供一点空间来记录数据。对于每个唯一的

name
,我需要在
time
列中获取 5 分钟前的 12:00:00 NZST 时间(以秒为单位的纪元)(在 SQLite 数据库中,不会丢失任何秒)。并以 UTC '%Y-%m-%dT%H:%M:%SZ' 格式输出。

创建数据:

import sqlite3
import random
from datetime import datetime, timedelta

conn = sqlite3.connect('your_database.db')
c = conn.cursor()

# Create the table
c.execute('''
    CREATE TABLE your_table (
        name TEXT,
        value REAL,
        time INTEGER
    )
''')

# Start time at 11:55pm
start_time = datetime.now().replace(hour=23, minute=55, second=0)

# Insert data from 11:55pm to 12:10am
for i in range((10 + 5) * 60):  # 10 minutes before and 5 minutes after midnight
    current_time = start_time + timedelta(seconds=i)
    epoch_time = int(current_time.timestamp())
    for name in ['1', '2', '3']:
        value = random.random()
        c.execute('INSERT INTO your_table VALUES (?, ?, ?)', (name, value, epoch_time))

# Commit the changes and close the connection
conn.commit()
conn.close()

我期望的结果:

utc_time             name           value
------------------------------------------
xxxxx11:00:00         1              100
xxxxx11:00:00         2              200 
sql sqlite
1个回答
0
投票

也许以下可以作为基础。

  • 您的问题中有些内容似乎不相符,例如%H 是 24 小时制的小时,午夜实际是第二天的 00:00:00。

无论如何,也许以下内容可能是您想要的基础。

  • 请注意,结果输出中已包含其他数据,希望有助于理解各个方面。

它自己的查询:-

WITH local_utc_modifier(lum) AS 
    /* CTE (Common Table Expression a temp table) with the difference between local and utc (not sure - is correct but principle IF device is setup accordingly)*/
    (SELECT (strftime('%s','now','localtime')) - (strftime('%s','now','UTC')))
SELECT
    name,
    (SELECT lum FROM local_utc_modifier) AS lum , /* the modifier value: include to demonstrate  <<<<<<<<<<EXTRA>>>>>>>>>>*/ 
    strftime('%Y-%m-%dT%H:%M:%SZ',time,'unixepoch','-'||(SELECT * FROM local_utc_modifier)||' seconds') /* output value */ AS time,
    value, /* NOTE ARBRITRAY */
    max(value) AS maxv, /* include to demonstrate arbrtrary value <<<<<<<<<<EXTRA>>>>>>>>>>*/
    min(value) AS minv, /* as prev <<<<<<<<<<EXTRA>>>>>>>>>>*/
    avg(value) AS avgv, /* as prev <<<<<<<<<<EXTRA>>>>>>>>>>*/
    count() AS number_found /* more than 1!!!! SEE ABOVE RESULTS <<<<<<<<<<EXTRA>>>>>>>>>> */
    
FROM your_table
/* Only midnight rows to a second */
WHERE strftime('%H:%M:%S',time,'unixepoch','-'||(SELECT * FROM local_utc_modifier)||' seconds') = '00:00:00'
    /* MIGHT WANT ADDITIONAL CONDITION JUST FOR CURRENT DATE */
/* Note if only 1 row per name then no need for GROUP BY HOWEVER MUST NOT THEN HAVE aggregate functions (count,max,min,avg) */
GROUP BY name
;
  • 请参阅评论,因为查询的某些部分您可能不想要/不需要。

上述演示:-

DROP TABLE IF EXISTS your_table;
CREATE TABLE IF NOT EXISTS your_table (
        name TEXT,
        value REAL,
        time INTEGER
);

/* Insert some testing data */
INSERT INTO your_table (name,value,time) 
    VALUES
    (1,100,1695765399),(2,200,1695765405),(3,300,1695765410),(3,10,1695765415),(2,20,1695765420),
    /* these ones are at midnight*/
    (1,100,1695765420 + 180),(1,15,1695765600),(2,222,1695765600),(3,333,1695765600),
    /* 1 second past midnight */
    (5,555,1695765601)
    ;
SELECT name, value, datetime(time,'unixepoch') AS easyreadtime, time FROM your_table;
WITH local_utc_modifier(lum) AS 
    /* CTE (Common Table Expression a temp table) with the difference between local and utc (not sure - is correct but principle IF device is setup accordingly)*/
    (SELECT (strftime('%s','now','localtime')) - (strftime('%s','now','UTC')))
SELECT
    name,
    (SELECT lum FROM local_utc_modifier) AS lum , /* the modifier value: include to demonstrate  <<<<<<<<<<EXTRA>>>>>>>>>>*/ 
    strftime('%Y-%m-%dT%H:%M:%SZ',time,'unixepoch','-'||(SELECT * FROM local_utc_modifier)||' seconds') /* output value */ AS time,
    value, /* NOTE ARBRITRAY */
    max(value) AS maxv, /* include to demonstrate arbrtrary value <<<<<<<<<<EXTRA>>>>>>>>>>*/
    min(value) AS minv, /* as prev <<<<<<<<<<EXTRA>>>>>>>>>>*/
    avg(value) AS avgv, /* as prev <<<<<<<<<<EXTRA>>>>>>>>>>*/
    count() AS number_found /* more than 1!!!! SEE ABOVE RESULTS <<<<<<<<<<EXTRA>>>>>>>>>> */
    
FROM your_table
/* Only midnight rows to a second */
WHERE strftime('%H:%M:%S',time,'unixepoch','-'||(SELECT * FROM local_utc_modifier)||' seconds') = '00:00:00'
    /* MIGHT WANT ADDITIONAL CONDITION JUST FOR CURRENT DATE */
/* Note if only 1 row per name then no need for GROUP BY HOWEVER MUST NOT THEN HAVE aggregate functions (count,max,min,avg) */
GROUP BY name
;

DROP TABLE IF EXISTS your_table; /* CLEANUP DEMO ENVIRONMENT */
  • 重要以上均使用AEST时间,因此测试数据需要考虑时区差异。 运行上述命令后,结果为:-

  • 第一次加载的数据SELECT:-

- note the 2 highlighted name **1** rows both are at midnight (to demonstrate GROUP BY and aggregate functions)
  • 结果,按照对你的问题的解释:-

  • 第二列是额外的,只是为了根据设备向您显示本地和 utc 之间的时差(AEST 时间)。
  • 最后四列演示了聚合函数分组。

聚合函数和 GROUP BY

对于名称 1,number_found(来自

count
函数)显示有 2 行与 WHERE 条件匹配(可能注意大小写)。 GROUP BY 子句定义了将被视为聚合函数所应用的组的行集,请注意,对于组,将输出 1 行。

省略 GROUP BY 子句,如果使用任何聚合函数,则所有输出都被视为 1 组。

如果选择输出一列并且它不受聚合表达式的影响,则提取的值将是组中某一行的值。它是一个任意值(例如,对于提取的值列

15
,它可能是
100
)(显示最大值、最小值和平均值)

© www.soinside.com 2019 - 2024. All rights reserved.