2010-12-13 52 views
27

Tôi có ngày được lưu trữ dưới dạng chuỗi trong cơ sở dữ liệu sqlite như "28/11/2010". Tôi muốn chuyển đổi chuỗi cho đến nay.Chuỗi chuyển đổi Sqlite đến ngày

Cụ thể tôi phải chuyển đổi nhiều ngày chuỗi giữa hai ngày.

Trong postgresql, tôi sử dụng to_date('30/11/2010','dd/MM/yyyy'), làm cách nào tôi có thể làm điều tương tự với sqlite?

Something như thế này:

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

Trả lời

46

Như Sqlite doesn't have a date type bạn sẽ cần phải làm so sánh chuỗi để đạt được điều này. Cho rằng để làm việc bạn cần phải đảo ngược thứ tự - ví dụ như từ dd/MM/yyyy để yyyyMMdd, sử dụng một cái gì đó giống như

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

+1: Nếu ngày đã được định dạng theo thứ gì đó mà chức năng xử lý ngày của SQLite hiểu, có thể làm điều gì đó thông minh hơn. (Hoặc nếu ngày đã được chuyển đổi sang ngày julian trước khi lưu trữ trong DB.) Nhưng nó đã không được, và "ngày" cần phải được sửa chữa. Tất nhiên, anh ta cũng có thể thử thêm chức năng 'to_date' của riêng mình, nhưng làm thế nào để làm điều đó phụ thuộc vào những gì SQLite được nhúng vào (mà chúng ta không biết). –

+1

@Donal tái tạo chức năng 'to_date' của riêng mình, cá cược mà không phải tất cả các chuỗi trong trường đó không phải là ngày hợp lệ :-) –

8

Một điều bạn nên nhìn vào là SQLite date and time functions, đặc biệt là nếu bạn đang đi để phải thao tác rất nhiều ngày. Đó là cách lành mạnh để sử dụng ngày, với chi phí thay đổi định dạng nội bộ (phải là ISO, tức là yyyy-MM-dd).

+3

Tài liệu này đã hết và được trích dẫn ... Tuy nhiên, IMO cần phải được làm lại tìm thông tin nhanh chóng. Tất cả các chi tiết có ý nghĩa được chôn cất. Ví dụ, có thể xác định kiểu trả về của hàm strftime ngay từ cái nhìn đầu tiên trong chưa đầy 10 giây ...? Không! Trong bất kỳ javadoc phong nha nó khả thi. – Stephan

+0

Nó được trích dẫn bởi vì nó thậm chí còn bị bỏ qua nhiều hơn, nhưng được cấp nó có thể làm với một bản làm lại. – MPelletier

16

Ngày được lưu dưới dạng TEXT (20/10/2013 03:26) Để thực hiện truy vấn và chọn hồ sơ giữa các ngày?

Better phiên bản là:

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

các substr từ 20/10/2013 cho 20.131.020 ngày định dạng DATE (20.131.021) - mà làm cho SQL làm việc với ngày và sử dụng các hàm ngày tháng và thời gian.

HOẶC

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

và ở đây là trong một dòng

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

này là dành cho fecha (TEXT) Ngày định dạng YYYY-MM-dd HH: mm: ss ví dụ tôi muốn tất cả các hồ sơ của 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); 
3

Phương pháp UDF là sở thích của tôi so với giòn substr val ues.

#!/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() 

này sẽ cung cấp cho bạn những kết quả này:

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

Các SQLite tương đương với bất cứ điều gì này mạnh mẽ là một dệt rối của substrinstr cuộc gọi mà bạn nên tránh.

0

Tôi lưu trữ ngày là 'DD-MON-YYYY format (10-Jun-2016) và truy vấn bên dưới hoạt động để tôi tìm kiếm hồ sơ giữa 2 ngày.

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

Nếu định dạng ngày nguồn không nhất quán có một số vấn đề với chức năng substr, ví dụ::

1/1/2017hay1/11/2017hay11/11/2017hay1/1/17 , vv

Vì vậy, Tôi theo sau một apporach khác nhau bằng cách sử dụng một bảng tạm thời. Đoạn mã này xuất ra thời gian 'YYYY-MM-DD' + nếu tồn tại.

Lưu ý rằng phiên bản này chấp nhận định dạng Ngày/Tháng/Năm. Nếu bạn muốn Tháng/Ngày/Năm hoán đổi hai biến đầu tiên DayPartMonthPart. Ngoài ra, hai năm '44 -'99 giả định 1944-1999 trong khi '00 -'43 giả định 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; 
Các vấn đề liên quan