strftime strftime
с кодами процентов используется для преобразования объекта, уже рассматриваемого sqlite как datetime, во что-то еще, но вам нужно обратное, поэтому подход в вопросе не будет работать. Например, здесь мы конвертируем текущее время в строку дд-мм-гггг:
library(sqldf)
sqldf("select strftime('%d-%m-%Y', 'now') now")
## now
## 1 07-09-2014
Обсуждение. Поскольку в SQlite отсутствуют типы даты, справиться с этим немного обременительно, особенно с нестандартными форматами даты, состоящими из 1 или 2 цифр, но если вы действительно хотите использовать SQLite, мы можем сделать это утомительно разбирая строки даты. Использование fn$
из пакета gsubfn для интерполяции строк немного упрощает это.
Код ниже zero2d
выводит код SQL для добавления символа нуля к его входным данным, если это одна цифра. rmSlash
выводит код SQL для удаления любых косых черт в своем аргументе. Year
, Month
и Day
каждый выходной код SQL принимает символьную строку, представляющую дату в обсуждаемом формате, и извлекает указанный компонент, переформатируя его как двухзначную строку символов, заполненную нулями, в случае Month
и Day
. fmtDate
принимает символьную строку формы, показанной в вопросе для first_string
и second_string
, и выводит yyyy-mm-dd
символьную строку.
library(sqldf)
library(gsubfn)
zero2d <- function(x) sprintf("substr('0' || %s, -2)", x)
rmSlash <- function(x) sprintf("replace(%s, '/', '')", x)
Year <- function(x) sprintf("substr(%s, -4)", x)
Month <- function(x) {
y <- sprintf("substr(%s, instr(%s, '/') + 1, 2)", x, x)
zero2d(rmSlash(y))
}
Day <- function(x) {
y <- sprintf("substr(%s, 1, 2)", x)
zero2d(rmSlash(y))
}
fmtDate <- function(x) format(as.Date(x))
sql <- "select * from df2 where
`Year('Date')` || '-' ||
`Month('Date')` || '-' ||
`Day('Date')`
between '`fmtDate(first_date)`' and '`fmtDate(second_date)`'"
fn$sqldf(sql)
давая:
Date
1 1/11/2001
2 1/12/2002
3 1/11/2003
Примечания
1) Используемые функции SQLite instr
, replace
и substr
являются основными функциями sqlite
2) SQL. Фактический оператор SQL, который выполняется после fn$
выполнения подстановок, выглядит следующим образом (слегка переформатирован, чтобы соответствовать):
> cat( fn$identity(sql), "\n")
select * from df2 where
substr(Date, -4)
|| '-' ||
substr('0' || replace(substr(Date, instr(Date, '/') + 1, 2), '/', ''), -2)
|| '-' ||
substr('0' || replace(substr(Date, 1, 2), '/', ''), -2)
between '2001-11-01' and '2003-11-01'
3) источник осложнений. Основное затруднение - нестандартные 1-2 цифры дня и месяца. Если бы они были последовательно двухзначными, это сократилось бы до следующего:
first_date <- "2001-11-01"
second_date <- ""2003-11-01"
fn$sqldf("select Date from df2
where substr(Date, -4) || '-' ||
substr(Date, 4, 2) || '-' ||
substr(Date, 1, 2)
between '`first_date`' and '`second_date`' ")
4) H2 Вот раствор H2. H2 действительно имеет тип datetime, существенно упрощающий решение по сравнению с SQLite. Мы предполагаем, что данные находятся в файле с именем mydata.dat
. Обратите внимание, что read.csv.sql
не поддерживает H2, поскольку H2 уже имеет для этого внутреннюю функцию csvread
SQL:
library(RH2)
library(sqldf)
first_date <- "2001-11-01"
second_date <- "2003-11-01"
fn$sqldf(c("CREATE TABLE t(DATE TIMESTAMP) AS
SELECT parsedatetime(DATE, 'd/M/y') as DATE
FROM CSVREAD('mydata.dat')",
"SELECT DATE FROM t WHERE DATE between '`first_date`' and '`second_date`'"))
Обратите внимание, что первый запрос RH2 будет медленным в сеансе, поскольку он загружает java. После этого вы можете попробовать его, чтобы убедиться, что производительность адекватна.
person
G. Grothendieck
schedule
07.09.2014
1/1/2011
, а не01/01/2011
. И в любом случае, я думаю,strftime
функция драйвераSQLite
сможет преобразовать в более поздний формат. Моя трудность в том, что я не знаю, как проверить функциюstrftime
в этом случае. - person biocyberman   schedule 08.09.2014strftime
для преобразования строк времени в даты на лету и сравнения этих дат. Я просто не знаком с функцией правильного вызова. - person biocyberman   schedule 08.09.2014