强制 dbGetQuery 为 Return POSIXct 时间戳
Force dbGetQuery to Return POSIXct Timestamp
我正在从 SQL 服务器数据库中提取数据,其中每一行都使用 ISO 时间戳作为其键。在数据库中,时间戳存储为 datetime2
数据类型。
当我运行下面的语句:
data <- dbGetQuery(con, "SELECT timestamp from table1")
它returns一个时间戳列是chr类型的数据框。这是数据框上的 str() returns:
$ timestamp: chr "2020-03-25 12:19:48.0000000" "2020-03-25 12:20:48.0000000"...
有了这个,我可以使用以下代码将它转换回 POSIXct 对象:
data$timestamp <- as.POSIXct(data$timestamp, format = '%Y-%m-%d %H:%M:%S')
但是,数据库每分钟(有时每秒)都会存储值,因此如果我尝试使用 as.POSIXct() 函数转换几个月或几年的时间戳,它可能需要长时间(以分钟为单位)。提取那么多数据时(在几秒范围内),dbGetQuery 函数相对较快。
dbGetQuery 或其他方法中是否有参数直接将时间戳解释为日期时间,而不是字符串?
这是我的连接命令:
con <- dbConnect(odbc(),
Driver = "SQL Server",
Server = "server1",
Database = "db1",
UID = "user",
PWD = "pwd")
TL;DR
(根据我的评论更新了一点)
DBI::dbGetQuery(con, "select cast ( SYSDATETIMEOFFSET() at time zone 'UTC' as DATETIME ) as now")
# now
# 1 2020-03-25 20:30:33.026
Sys.time()
# [1] "2020-03-25 13:30:31.177 PDT"
(我的笔记本电脑和远程 sql 服务器不同步)
说明
odbc
驱动程序(使用 nanodbc
C++ 库) 将 识别 SQL 服务器类型 DATETIME
的数据。但是,此类型不包括时区,因此如果两行未引用相同的时区,则简化数据可能会引入错误。
DBI::dbExecute(con, "create table r2mt (id INTEGER, tm DATETIMEOFFSET)")
# [1] 0
DBI::dbExecute(con, "insert into r2mt (id,tm) values (1,'2020-03-23 12:34:56 +00:00'),(2,'2020-03-23 12:34:56.100 -04:00')")
# [1] 2
dat <- DBI::dbGetQuery(con, "select id, tm from r2mt")
str(dat)
# 'data.frame': 2 obs. of 2 variables:
# $ id: int 1 2
# $ tm: chr "2020-03-23 12:34:56.0000000 +00:00" "2020-03-23 12:34:56.5000000 -04:00"
as.POSIXct(gsub("([-+]?[0-9]{2}):([0-9]{2})$", "\1\2", dat$tm),
format = "%Y-%m-%d %H:%M:%OS %z")
# [1] "2020-03-23 05:34:56.0 PDT" "2020-03-23 09:34:56.5 PDT"
diff( as.POSIXct(gsub("([-+]?[0-9]{2}):([0-9]{2})$", "\1\2", dat$tm),
format = "%Y-%m-%d %H:%M:%OS %z") )
# Time difference of 4.000139 hours
dat <- DBI::dbGetQuery(con, "select id, cast(tm as DATETIME) as tm from r2mt")
str(dat)
# 'data.frame': 2 obs. of 2 variables:
# $ id: int 1 2
# $ tm: POSIXct, format: "2020-03-23 12:34:56.0" "2020-03-23 12:34:56.5"
diff(dat$tm)
# Time difference of 0.5 secs
(在 R 中,时区是整个列向量的一个属性,因此不会因该列中的不同元素而异。)
由于您尝试在 SQL 中做尽可能多的事情(好主意),当您投射到 DATETIME
class 时,请确保强制设置时区对于所有人,以便至少所有时间都具有可比性。
dat <- DBI::dbGetQuery(con, "select id, cast(tm at time zone 'UTC' as DATETIME) as tm from r2mt")
str(dat)
# 'data.frame': 2 obs. of 2 variables:
# $ id: int 1 2
# $ tm: POSIXct, format: "2020-03-23 12:34:56.0" "2020-03-23 16:34:56.5"
dat <- DBI::dbGetQuery(con, "select id, cast(tm at time zone 'Central European Standard Time' as datetime) as tm from r2mt")
str(dat)
# 'data.frame': 2 obs. of 2 variables:
# $ id: int 1 2
# $ tm: POSIXct, format: "2020-03-23 13:34:56.0" "2020-03-23 17:34:56.5"
(不幸的是,SQL 服务器中使用的时区与 R 中使用的时区不同。我更喜欢 'UTC'
,因为没有歧义,交给你了。)
我正在从 SQL 服务器数据库中提取数据,其中每一行都使用 ISO 时间戳作为其键。在数据库中,时间戳存储为 datetime2
数据类型。
当我运行下面的语句:
data <- dbGetQuery(con, "SELECT timestamp from table1")
它returns一个时间戳列是chr类型的数据框。这是数据框上的 str() returns:
$ timestamp: chr "2020-03-25 12:19:48.0000000" "2020-03-25 12:20:48.0000000"...
有了这个,我可以使用以下代码将它转换回 POSIXct 对象:
data$timestamp <- as.POSIXct(data$timestamp, format = '%Y-%m-%d %H:%M:%S')
但是,数据库每分钟(有时每秒)都会存储值,因此如果我尝试使用 as.POSIXct() 函数转换几个月或几年的时间戳,它可能需要长时间(以分钟为单位)。提取那么多数据时(在几秒范围内),dbGetQuery 函数相对较快。
dbGetQuery 或其他方法中是否有参数直接将时间戳解释为日期时间,而不是字符串?
这是我的连接命令:
con <- dbConnect(odbc(),
Driver = "SQL Server",
Server = "server1",
Database = "db1",
UID = "user",
PWD = "pwd")
TL;DR
(根据我的评论更新了一点)
DBI::dbGetQuery(con, "select cast ( SYSDATETIMEOFFSET() at time zone 'UTC' as DATETIME ) as now")
# now
# 1 2020-03-25 20:30:33.026
Sys.time()
# [1] "2020-03-25 13:30:31.177 PDT"
(我的笔记本电脑和远程 sql 服务器不同步)
说明
odbc
驱动程序(使用 nanodbc
C++ 库) 将 识别 SQL 服务器类型 DATETIME
的数据。但是,此类型不包括时区,因此如果两行未引用相同的时区,则简化数据可能会引入错误。
DBI::dbExecute(con, "create table r2mt (id INTEGER, tm DATETIMEOFFSET)")
# [1] 0
DBI::dbExecute(con, "insert into r2mt (id,tm) values (1,'2020-03-23 12:34:56 +00:00'),(2,'2020-03-23 12:34:56.100 -04:00')")
# [1] 2
dat <- DBI::dbGetQuery(con, "select id, tm from r2mt")
str(dat)
# 'data.frame': 2 obs. of 2 variables:
# $ id: int 1 2
# $ tm: chr "2020-03-23 12:34:56.0000000 +00:00" "2020-03-23 12:34:56.5000000 -04:00"
as.POSIXct(gsub("([-+]?[0-9]{2}):([0-9]{2})$", "\1\2", dat$tm),
format = "%Y-%m-%d %H:%M:%OS %z")
# [1] "2020-03-23 05:34:56.0 PDT" "2020-03-23 09:34:56.5 PDT"
diff( as.POSIXct(gsub("([-+]?[0-9]{2}):([0-9]{2})$", "\1\2", dat$tm),
format = "%Y-%m-%d %H:%M:%OS %z") )
# Time difference of 4.000139 hours
dat <- DBI::dbGetQuery(con, "select id, cast(tm as DATETIME) as tm from r2mt")
str(dat)
# 'data.frame': 2 obs. of 2 variables:
# $ id: int 1 2
# $ tm: POSIXct, format: "2020-03-23 12:34:56.0" "2020-03-23 12:34:56.5"
diff(dat$tm)
# Time difference of 0.5 secs
(在 R 中,时区是整个列向量的一个属性,因此不会因该列中的不同元素而异。)
由于您尝试在 SQL 中做尽可能多的事情(好主意),当您投射到 DATETIME
class 时,请确保强制设置时区对于所有人,以便至少所有时间都具有可比性。
dat <- DBI::dbGetQuery(con, "select id, cast(tm at time zone 'UTC' as DATETIME) as tm from r2mt")
str(dat)
# 'data.frame': 2 obs. of 2 variables:
# $ id: int 1 2
# $ tm: POSIXct, format: "2020-03-23 12:34:56.0" "2020-03-23 16:34:56.5"
dat <- DBI::dbGetQuery(con, "select id, cast(tm at time zone 'Central European Standard Time' as datetime) as tm from r2mt")
str(dat)
# 'data.frame': 2 obs. of 2 variables:
# $ id: int 1 2
# $ tm: POSIXct, format: "2020-03-23 13:34:56.0" "2020-03-23 17:34:56.5"
(不幸的是,SQL 服务器中使用的时区与 R 中使用的时区不同。我更喜欢 'UTC'
,因为没有歧义,交给你了。)