2010-12-13 16 views
27

"28/11/2010" gibi bir sqlite veritabanında dize olarak depolanmış bir tarihim var. Dizeyi tarihe dönüştürmek istiyorum.Sqlite dizgi, dönüştürülecek tarihi

Özellikle iki tarih arasındaki çok sayıda dize tarihini dönüştürmem gerekiyor.

Postgresql'de to_date('30/11/2010','dd/MM/yyyy') kullanıyorum, aynı şeyi sqlite ile nasıl yapabilirim? Böyle

şey:

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') 

cevap

46

SQLite doesn't have a date type olarak bunu başarmak için dize karşılaştırma yapmak gerekecektir. Bu Sırayı tersine gerekir çalışması için - YYYYAAGG için gg/AA/yyyy gelen örneğin, bir şey kullanarak içine bakmak gerekir

where substr(column,7)||substr(column,4,2)||substr(column,1,2) 
     between '20101101' and '20101130' 
+1

+1: tarih SQLite'nın tarihinde taşıma işlevleri anlama şey biçimlendirilmiş olsaydı, o akıllı bir şey yapmak mümkün olurdu. (Ya da tarih DB'de saklanmadan önce julian günlerine çevrilmişse.) Ama değildi ve “tarih” in onarılması gerekiyor. Elbette, kendi "to_date" fonksiyonunu da eklemeyi deneyebilirdi, fakat bunun nasıl yapılacağı, SQLite'nin gömülü olduğu (hangisi bilmediğimize) bağlıdır. –

+1

@Donal kendi "to_date" işlevini yaratırken, bu alandaki tüm dizelerin geçerli olmadığı tarihler nedir? :-) –

8

Bir şey gibi bunu yapmak zorunda olacak, özellikle eğer SQLite date and time functions olduğunu birçok tarihi işlemek. İçsel formatı değiştirmenin bedeli olarak, tarihleri ​​kullanmak için aklı başında bir yoldur (ISO, yani yyyy-MM-dd olmak zorundadır).

+3

Bu dökümantasyon bitmek bilmez ... Ancak, IMO'nun yeniden çalıştırılması gerekiyor bilgileri çabuk bulmak. Bütün anlamlı detaylar gömülü. Örneğin, ilk görüşte strftime fonksiyonunun dönüş tipini 10 saniyeden daha az olarak belirlemek mümkün mü? Yok hayır ! Herhangi bir iyi javadoc içinde mümkün. – Stephan

+0

Daha fazla alıntı yapıldı çünkü daha fazla göz ardı edildi, ancak bir yeniden çalışma ile yapılabilir. – MPelletier

16

Kayıt tarihi TARİH (20/10/2013 03:26) Tarihler arasındaki sorguları seçmek ve seçmek için?

Daha İyi sürümü: 20/10/2013 den

SELECT TIMSTARTTIMEDATE 
FROM TIMER 
WHERE DATE(substr(TIMSTARTTIMEDATE,7,4) 
||substr(TIMSTARTTIMEDATE,4,2) 
||substr(TIMSTARTTIMEDATE,1,2)) 
BETWEEN DATE(20131020) AND DATE(20131021); 

substr 20131020 tarih formatı TARİHİ (20131021) verir - SQL tarihleri ​​ile çalışma ve tarih ve saat işlevleri kullanarak yapar. Burada

VEYA

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'); 

ve bir satır

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'); 
0

Bu Fecha içindir içindedir (METİN) formatında tarih YYYY-AA-gg SS: dd: Örneğin ss tek istediğim ene-05-2014 kayıtları (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); 
3

UDF yaklaşımı benim tercih kırılgan substr val karşılaştırılır evet.

#!/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 __name__ == "__main__": 
    main() 

Bu size şu sonuçlar verecektir:

[{'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'}] 

bu sağlam bir şey SQLite eşdeğer kaçınmalısınız substr ve instr aramaların karışık örgü olduğunu.

0

Tarihi 2 günlük tarih aralığındaki kayıtları aramak için "DD-MON-YYYY biçimi (10 Haziran 2016) ve sorgulamanın altında çalışıyorum. Kaynak Tarih biçimi tutarlı değilse

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'); 
1

substr fonksiyonu, örneğin bazı sorun var: Vb

1/1/2017veya1/11/2017veya11/11/2017veya1/1/17

Yani Geçici bir tablo kullanarak farklı bir uygulama takip ettim. Bu pasaj varsa 'YYYY-AA-GG' + zamanını verir.

Bu sürümün Day/Month/Year biçimini kabul ettiğini unutmayın. Ay/Gün/Yıl öğesinin ilk iki değişkeni DayPart ve MonthPart değiştirmesini isterseniz. Ayrıca, iki yıllık tarihler '44 -'99, 1944-1999'u alırken, '00 -'43 ise 2000-2043'ü varsayıyor.

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;