「28/11/2010」のようなsqliteデータベースに文字列として保存された日付があります。文字列を日付に変換したい。
具体的には、2つの日付の間で多くの文字列の日付を変換する必要があります。
Postgresqlでは、to_date('30/11/2010','dd/MM/yyyy')
を使用していますが、sqliteでも同じことができますか?
このようなもの:
SELECT * FROM table
WHERE to_date(column,'dd/MM/yyyy')
BETWEEN to_date('01/11/2010','dd/MM/yyyy')
AND to_date('30/11/2010','dd/MM/yyyy')
Sqlite 日付型を持たない として、これを実現するには文字列比較を行う必要があります。そのためには、順序を逆にする必要があります-たとえば、dd/MM/yyyyからyyyyMMddのように、
where substr(column,7)||substr(column,4,2)||substr(column,1,2)
between '20101101' and '20101130'
TEXTとして保存された日付(20/10/2013 03:26)クエリを実行し、日付間のレコードを選択するには?
より良いバージョンは:
SELECT TIMSTARTTIMEDATE
FROM TIMER
WHERE DATE(substr(TIMSTARTTIMEDATE,7,4)
||substr(TIMSTARTTIMEDATE,4,2)
||substr(TIMSTARTTIMEDATE,1,2))
BETWEEN DATE(20131020) AND DATE(20131021);
20/10/2013のsubstrは、20131020日付形式DATE(20131021)を提供します。これにより、SQLが日付を処理し、日付と時刻の関数を使用するようになります。
OR
SELECT TIMSTARTTIMEDATE
FROM TIMER
WHERE DATE(substr(TIMSTARTTIMEDATE,7,4)
||'-'
||substr(TIMSTARTTIMEDATE,4,2)
||'-'
||substr(TIMSTARTTIMEDATE,1,2))
BETWEEN DATE('2013-10-20') AND DATE('2013-10-21');
そして、ここは一行です
SELECT TIMSTARTTIMEDATE FROM TIMER WHERE DATE(substr(TIMSTARTTIMEDATE,7,4)||'-'||substr(TIMSTARTTIMEDATE,4,2)||'-'||substr(TIMSTARTTIMEDATE,1,2)) BETWEEN DATE('2013-10-20') AND DATE('2013-10-21');
検討する必要があるものの1つは、 SQLiteの日付と時刻の関数 です。特に、多くの日付を操作する必要がある場合です。内部形式を変更することを犠牲にして、日付を使用するのが正しい方法です(ISO、つまりyyyy-MM-ddでなければなりません)。
UDFアプローチは、脆いsubstr
値と比較して私の好みです。
#!/usr/bin/env python3
import sqlite3
from dateutil import parser
from pprint import pprint
def date_parse(s):
''' Converts a string to a date '''
try:
t = parser.parse(s, parser.parserinfo(dayfirst=True))
return t.strftime('%Y-%m-%d')
except:
return None
def dict_factory(cursor, row):
''' Helper for dict row results '''
d = {}
for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx]
return d
def main():
''' Demonstrate UDF '''
with sqlite3.connect(":memory:") as conn:
conn.row_factory = dict_factory
setup(conn)
##################################################
# This is the code that matters. The rest is setup noise.
conn.create_function("date_parse", 1, date_parse)
cur = conn.cursor()
cur.execute(''' select "date", date_parse("date") as parsed from _test order by 2; ''')
pprint(cur.fetchall())
##################################################
def setup(conn):
''' Setup some values to parse '''
cur = conn.cursor()
# Make a table
sql = '''
create table _test (
"id" integer primary key,
"date" text
);
'''
cur.execute(sql)
# Fill the table
dates = [
'2/1/03', '03/2/04', '4/03/05', '05/04/06',
'6/5/2007', '07/6/2008', '8/07/2009', '09/08/2010',
'2-1-03', '03-2-04', '4-03-05', '05-04-06',
'6-5-2007', '07-6-2008', '8-07-2009', '09-08-2010',
'31/12/20', '31-12-2020',
'BOMB!',
]
params = [(x,) for x in dates]
cur.executemany(''' insert into _test ("date") values(?); ''', params)
if __== "__main__":
main()
これにより、次の結果が得られます。
[{'date': 'BOMB!', 'parsed': None},
{'date': '2/1/03', 'parsed': '2003-01-02'},
{'date': '2-1-03', 'parsed': '2003-01-02'},
{'date': '03/2/04', 'parsed': '2004-02-03'},
{'date': '03-2-04', 'parsed': '2004-02-03'},
{'date': '4/03/05', 'parsed': '2005-03-04'},
{'date': '4-03-05', 'parsed': '2005-03-04'},
{'date': '05/04/06', 'parsed': '2006-04-05'},
{'date': '05-04-06', 'parsed': '2006-04-05'},
{'date': '6/5/2007', 'parsed': '2007-05-06'},
{'date': '6-5-2007', 'parsed': '2007-05-06'},
{'date': '07/6/2008', 'parsed': '2008-06-07'},
{'date': '07-6-2008', 'parsed': '2008-06-07'},
{'date': '8/07/2009', 'parsed': '2009-07-08'},
{'date': '8-07-2009', 'parsed': '2009-07-08'},
{'date': '09/08/2010', 'parsed': '2010-08-09'},
{'date': '09-08-2010', 'parsed': '2010-08-09'},
{'date': '31/12/20', 'parsed': '2020-12-31'},
{'date': '31-12-2020', 'parsed': '2020-12-31'}]
この堅牢なものと同等のSQLiteは、substr
とinstr
呼び出しの絡み合った織り方であり、避けるべきです。
ソース日付形式が一貫していない場合、substr
関数に問題があります。例:
1/1/2017または1/11/2017または11/11/2017または1/1/17など.
そこで、一時テーブルを使用して別のアプローチに従いました。このスニペットは、 'YYYY-MM-DD' +時間(存在する場合)を出力します。
このバージョンは日/月/年形式を受け入れます。月/日/年が必要な場合は、最初の2つの変数DayPart
とMonthPart
を交換します。また、2年の日付'44 -'99は1944-1999を想定していますが、'00 -'43は2000-2043を想定しています。
BEGIN;
CREATE TEMP TABLE [DateconvertionTable] (Id TEXT PRIMARY KEY, OriginalDate TEXT , SepA INTEGER, DayPart TEXT,Rest1 TEXT, SepB INTEGER, MonthPart TEXT, Rest2 TEXT, SepC INTEGER, YearPart TEXT, Rest3 TEXT, NewDate TEXT);
INSERT INTO [DateconvertionTable] (Id,OriginalDate) SELECT SourceIdColumn, SourceDateColumn From [SourceTable];
--day Part (If day is first)
UPDATE [DateconvertionTable] SET SepA=instr(OriginalDate ,'/');
UPDATE [DateconvertionTable] SET DayPart=substr(OriginalDate,1,SepA-1) ;
UPDATE [DateconvertionTable] SET Rest1=substr(OriginalDate,SepA+1);
--Month Part (If Month is second)
UPDATE [DateconvertionTable] SET SepB=instr(Rest1,'/');
UPDATE [DateconvertionTable] SET MonthPart=substr(Rest1, 1,SepB-1);
UPDATE [DateconvertionTable] SET Rest2=substr(Rest1,SepB+1);
--Year Part (3d)
UPDATE [DateconvertionTable] SET SepC=instr(Rest2,' ');
--Use Cases In case of time string included
UPDATE [DateconvertionTable] SET YearPart= CASE WHEN SepC=0 THEN Rest2 ELSE substr(Rest2,1,SepC-1) END;
--The Rest considered time
UPDATE [DateconvertionTable] SET Rest3= CASE WHEN SepC=0 THEN '' ELSE substr(Rest2,SepC+1) END;
-- Convert 1 digit day and month to 2 digit
UPDATE [DateconvertionTable] SET DayPart=0||DayPart WHERE CAST(DayPart AS INTEGER)<10;
UPDATE [DateconvertionTable] SET MonthPart=0||MonthPart WHERE CAST(MonthPart AS INTEGER)<10;
--If there is a need to convert 2 digit year to 4 digit year, make some assumptions...
UPDATE [DateconvertionTable] SET YearPart=19||YearPart WHERE CAST(YearPart AS INTEGER)>=44 AND CAST(YearPart AS INTEGER)<100;
UPDATE [DateconvertionTable] SET YearPart=20||YearPart WHERE CAST(YearPart AS INTEGER)<44 AND CAST(YearPart AS INTEGER)<100;
UPDATE [DateconvertionTable] SET NewDate = YearPart || '-' || MonthPart || '-' || DayPart || ' ' || Rest3;
UPDATE [SourceTable] SET SourceDateColumn=(Select NewDate FROM DateconvertionTable WHERE [DateconvertionTable].id=SourceIdColumn);
END;
日付を 'DD-MON-YYYY形式(2016年6月10日)として保存していますが、2つの日付の間でレコードを検索するクエリが機能します。
select date, substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), case
substr(date, 4,3)
when 'Jan' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'Jan' , '01'))
when 'Feb' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'Feb' , '02'))
when 'Mar' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'Mar' , '03'))
when 'Apr' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'Apr' , '04'))
when 'May' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'May' , '05'))
when 'Jun' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'Jun' , '06'))
when 'Jul' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'Jul' , '07'))
when 'Aug' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'Aug' , '08'))
when 'Sep' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'Sep' , '09'))
when 'Oct' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'Oct' , '10'))
when 'Nov' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'Nov' , '11'))
when 'Dec' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'Dec' , '12'))
else '0' end as srcDate from payment where srcDate >= strftime('%s', '2016-07-06') and srcDate <= strftime('%s', '2016-09-06');
これはfecha(TEXT)形式の日付YYYY-MM-dd HH:mm:ss用です。たとえば、Ene-05-2014(2014-01-05)のすべてのレコードが必要です。
SELECT
fecha
FROM
Mytable
WHERE
DATE(substr(fecha ,1,4) ||substr(fecha ,6,2)||substr(fecha ,9,2))
BETWEEN
DATE(20140105)
AND
DATE(20140105);
日付がd F Y
形式(2017年11月20日)で保存されているデータベースがあり、それを機械可読な日付(Y-m-d)に変換するために、このメソッドを使用してテーブル全体を適切な形式に更新します。
日付の書式設定のみが必要な場合は、内側を見て、日付の書式設定方法を選択します。
update TABLENAME as realTABLE set created_at = (
select
-- Get Year
substr(tmpTABLE.created_at ,-4, 4)
|| '-' ||
-- Get Month
substr(
replace (replace (replace (replace (replace (replace (replace (replace (replace (replace (replace (replace (tmpReis.szAanmaakDatum
, ' Dec ', '-12-') , ' Nov ', '-11-') , ' Oct ', '-10-') , ' Sep ', '-09-') , ' Aug ', '-08-') , ' Jul ', '-07-') , ' Jun ', '-06-') , ' May ', '-05-') , ' Apr ', '-04-') , ' Mar ', '-03-') , ' Feb ', '-02-') , ' Jan ', '-01-')
-- Get it from the original space location + 1, then get the two numbers.
,instr(tmpTABLE.created_at, ' ')+1, 2)
|| '-' ||
-- Get day, prepend with a zero if there's a zero lacking.
substr('00' || tmpTABLE.created_at, -2, 2) as foo
from TABLENAME as tmpTABLE
where tmpTABLE.id = realTABLE.id
-- Check for valid matching formats. don't do those that already were converted.
) where created_at like '_ ___ ____'
or created_at like '__ ___ ____';