如何根据日期和时间对sqlite表进行排序?

时间:2019-05-03 13:53:13

标签: android sqlite

我想根据日期和时间对表格进行排序。我的数据库在日期和时间上有两个单独的列,它们分别存储为字符串dd-MM-yyyy和HH:mm am / pm。如何对它们进行排序,以便最新条目显示在顶部?

2 个答案:

答案 0 :(得分:2)

您存储在数据库中的日期格式不具有可比性,因此您将始终必须处理此类问题。
最好将日期格式更改为YYYY-MM-DD,将时间格式更改为hh:mm
在此期间,您可以使用substr()

select * from tablename
order by 
  substr(datecol, 7) || substr(datecol, 4, 2)  || substr(datecol, 1, 2) DESC, 
  case length(timecol)
    when 8 then substr(timecol, 7) || substr(timecol, 1, 5)
    when 7 then substr('0' || timecol, 7) || substr('0' || timecol, 1, 5)
  end DESC

datecoltimecol更改为您的列名称。
这样会将日期格式更改为HHHHMMDD,将时间格式更改为AM/PM mm:HH,这些格式将仅在ORDER BY中使用。
正如我之前提到的,正确的解决方案是永久更改日期和时间的格式。

答案 1 :(得分:1)

我相信以下内容可以满足您的要求(假设表的名称为 mytable ,日期列的名称为 the_date ,时间列的名称为 the_time (显然会相应地更改这些值):-

SELECT *
FROM mytable 
ORDER BY
    CASE 
        WHEN (substr(the_date,2,1) = '-') AND (substr(the_date,4,1) = '-') THEN substr(the_date,5,4)||'0'||substr(the_date,3,1)||'0'||substr(the_date,1,1)
        WHEN substr(the_date,2,1) = '-' AND substr(the_date,5,1) = '-' THEN substr(the_date,6,4)||substr(the_date,3,2)||'0'||substr(the_date,1,1)
        WHEN substr(the_date,3,1) = '-' AND substr(the_date,5,1) = '-' THEN substr(the_date,6,4)||'0'||substr(the_date,4,1)||substr(the_date,1,2)
      WHEN substr(the_date,3,1) = '-' AND substr(the_date,6,1) = '-' THEN substr(the_date,7,4)||substr(the_date,4,2)||substr(the_date,1,2)
    END DESC
    ,
    CASE
        WHEN substr(the_time,2,1) = ':' AND instr(the_time,' ') = 4 AND instr(the_time,' am') THEN '0'||substr(the_time,1,1)||'0'||substr(the_time,3,1)
        WHEN substr(the_time,2,1) = ':' AND instr(the_time,' ') = 5 AND instr(the_time,' am') THEN '0'||substr(the_time,1,1)||substr(the_time,3,2)  
        WHEN substr(the_time,2,1) = ':' AND instr(the_time,' ') = 4 AND instr(the_time,' pm') THEN CAST(12 + CAST(substr(the_time,1,1) AS INTEGER) AS TEXT)||'0'||substr(the_time,3,1)
        WHEN substr(the_time,2,1) = ':' AND instr(the_time,' ') = 5 AND instr(the_time,' pm') THEN CAST(12 + CAST(substr(the_time,1,1) AS INTEGER) AS TEXT)||substr(the_time,3,2)       
        WHEN substr(the_time,3,1) = ':' AND instr(the_time,' ') = 5 AND instr(the_time,' am') THEN substr(the_time,1,2)||'0'||substr(the_time,4,1)
        WHEN substr(the_time,3,1) = ':' AND instr(the_time,' ') = 6 AND instr(the_time,' am') THEN substr(the_time,1,2)||substr(the_time,4,2)       
        WHEN substr(the_time,3,1) = ':' AND instr(the_time,' ') = 5 AND instr(the_time,' pm') THEN CAST(12 + CAST(substr(the_time,1,2) AS INTEGER) AS TEXT)||'0'||substr(the_time,4,1)
        WHEN substr(the_time,3,1) = ':' AND instr(the_time,' ') = 6 AND instr(the_time,' pm') THEN CAST(12 + CAST(substr(the_time,1,2) AS INTEGER) AS TEXT)||substr(the_time,4,2)
    END DESC
;

这将处理月份中的月份,年份中的月份,小时和分钟的一位或两位数的所有排列。

它不在乎 12:00 pm 解析为24:00(也就是说,当对 pm 进行编码时,每小时会增加12点(因此即使32:00 pm将被转换(这样),并视为第44小时))。下午00:00与上午12:00相同(因为小时数增加了12点)。

上面的测试是使用:-

DROP TABLE IF EXISTS mytable;
CREATE TABLE IF NOT EXISTS mytable (the_description TEXT, the_date TEXT, the_time TEXT);
INSERT INTO mytable VALUES
    ('REC001','1-1-2019','1:15 am'),
    ('REC002','11-2-2019','11:15 am'),
    ('REC003','2-11-2019','1:15 pm'),
    ('REC004','12-10-2019','11:15 pm'),
    ('REC005','3-2-2019','12:00 am'),
    ('REC006','4-3-2018','12:00 pm'),
    ('REC007','4-3-2018','12:1 am'),
    ('REC008','4-3-2018','1:1 pm')

;
SELECT * FROM mytable;
SELECT *,
    CASE 
        WHEN substr(the_date,2,1) = '-' AND (substr(the_date,4,1) = '-') THEN substr(the_date,5,4)||'0'||substr(the_date,3,1)||'0'||substr(the_date,1,1)
        WHEN substr(the_date,2,1) = '-' AND substr(the_date,5,1) = '-' THEN substr(the_date,6,4)||substr(the_date,3,2)||'0'||substr(the_date,1,1)
        WHEN substr(the_date,3,1) = '-' AND substr(the_date,5,1) = '-' THEN substr(the_date,6,4)||'0'||substr(the_date,4,1)||substr(the_date,1,2)
      WHEN substr(the_date,3,1) = '-' AND substr(the_date,6,1) = '-' THEN substr(the_date,7,4)||substr(the_date,4,2)||substr(the_date,1,2)
    END AS SORTdate,
    CASE
        WHEN substr(the_time,2,1) = ':' AND instr(the_time,' ') = 4 AND instr(the_time,' am') THEN '0'||substr(the_time,1,1)||'0'||substr(the_time,3,1)
        WHEN substr(the_time,2,1) = ':' AND instr(the_time,' ') = 5 AND instr(the_time,' am') THEN '0'||substr(the_time,1,1)||substr(the_time,3,2)  
        WHEN substr(the_time,2,1) = ':' AND instr(the_time,' ') = 4 AND instr(the_time,' pm') THEN CAST(12 + CAST(substr(the_time,1,1) AS INTEGER) AS TEXT)||'0'||substr(the_time,3,1)
        WHEN substr(the_time,2,1) = ':' AND instr(the_time,' ') = 5 AND instr(the_time,' pm') THEN CAST(12 + CAST(substr(the_time,1,1) AS INTEGER) AS TEXT)||substr(the_time,3,2)       
        WHEN substr(the_time,3,1) = ':' AND instr(the_time,' ') = 5 AND instr(the_time,' am') THEN substr(the_time,1,2)||'0'||substr(the_time,4,1)
        WHEN substr(the_time,3,1) = ':' AND instr(the_time,' ') = 6 AND instr(the_time,' am') THEN substr(the_time,1,2)||substr(the_time,4,2)       
        WHEN substr(the_time,3,1) = ':' AND instr(the_time,' ') = 5 AND instr(the_time,' pm') THEN CAST(12 + CAST(substr(the_time,1,2) AS INTEGER) AS TEXT)||'0'||substr(the_time,4,1)
        WHEN substr(the_time,3,1) = ':' AND instr(the_time,' ') = 6 AND instr(the_time,' pm') THEN CAST(12 + CAST(substr(the_time,1,2) AS INTEGER) AS TEXT)||substr(the_time,4,2)
    END AS sorttime
FROM mytable 
ORDER BY
    CASE 
        WHEN (substr(the_date,2,1) = '-') AND (substr(the_date,4,1) = '-') THEN substr(the_date,5,4)||'0'||substr(the_date,3,1)||'0'||substr(the_date,1,1)
        WHEN substr(the_date,2,1) = '-' AND substr(the_date,5,1) = '-' THEN substr(the_date,6,4)||substr(the_date,3,2)||'0'||substr(the_date,1,1)
        WHEN substr(the_date,3,1) = '-' AND substr(the_date,5,1) = '-' THEN substr(the_date,6,4)||'0'||substr(the_date,4,1)||substr(the_date,1,2)
      WHEN substr(the_date,3,1) = '-' AND substr(the_date,6,1) = '-' THEN substr(the_date,7,4)||substr(the_date,4,2)||substr(the_date,1,2)
    END DESC
    ,
    CASE
        WHEN substr(the_time,2,1) = ':' AND instr(the_time,' ') = 4 AND instr(the_time,' am') THEN '0'||substr(the_time,1,1)||'0'||substr(the_time,3,1)
        WHEN substr(the_time,2,1) = ':' AND instr(the_time,' ') = 5 AND instr(the_time,' am') THEN '0'||substr(the_time,1,1)||substr(the_time,3,2)  
        WHEN substr(the_time,2,1) = ':' AND instr(the_time,' ') = 4 AND instr(the_time,' pm') THEN CAST(12 + CAST(substr(the_time,1,1) AS INTEGER) AS TEXT)||'0'||substr(the_time,3,1)
        WHEN substr(the_time,2,1) = ':' AND instr(the_time,' ') = 5 AND instr(the_time,' pm') THEN CAST(12 + CAST(substr(the_time,1,1) AS INTEGER) AS TEXT)||substr(the_time,3,2)       
        WHEN substr(the_time,3,1) = ':' AND instr(the_time,' ') = 5 AND instr(the_time,' am') THEN substr(the_time,1,2)||'0'||substr(the_time,4,1)
        WHEN substr(the_time,3,1) = ':' AND instr(the_time,' ') = 6 AND instr(the_time,' am') THEN substr(the_time,1,2)||substr(the_time,4,2)       
        WHEN substr(the_time,3,1) = ':' AND instr(the_time,' ') = 5 AND instr(the_time,' pm') THEN CAST(12 + CAST(substr(the_time,1,2) AS INTEGER) AS TEXT)||'0'||substr(the_time,4,1)
        WHEN substr(the_time,3,1) = ':' AND instr(the_time,' ') = 6 AND instr(the_time,' pm') THEN CAST(12 + CAST(substr(the_time,1,2) AS INTEGER) AS TEXT)||substr(the_time,4,2)
    END DESC
;

初始排序时未排序的行:-

enter image description here

显示具有排序顺序字段(转换的日期和时间)的已排序行:-

enter image description here

其他

如果日期是使用YYYY-MM-DD HH:MM(或任何公认的格式Date And Time Functions - Time Strings)存储的,则只需对列进行排序(仅需要1列)。提取多种格式的数据也非常简单。

以下是批量更新的示例,该更新会将d(d)-m(m)-yyyy和h(h):m(m)格式(括在方括号中)将两列转换为单列值可能存在或不存在,具体取决于该值是否具有数十个数字。在示例中, the_date the_time 这两个列都进行了转换:-

WITH cte1(cte1id,date,time) AS
    (
        SELECT rowid,
            CASE 
                WHEN substr(the_date,2,1) = '-' AND (substr(the_date,4,1) = '-') 
                    THEN substr(the_date,5,4)||'-0'||substr(the_date,3,1)||'-0'||substr(the_date,1,1)
                WHEN substr(the_date,2,1) = '-' AND substr(the_date,5,1) = '-' 
                    THEN substr(the_date,6,4)||'-'||substr(the_date,3,2)||'-0'||substr(the_date,1,1)
                WHEN substr(the_date,3,1) = '-' AND substr(the_date,5,1) = '-' 
                    THEN substr(the_date,6,4)||'-0'||substr(the_date,4,1)||'-'||substr(the_date,1,2)
                WHEN substr(the_date,3,1) = '-' AND substr(the_date,6,1) = '-' 
                    THEN substr(the_date,7,4)||'-'||substr(the_date,4,2)||'-'||substr(the_date,1,2)
            END AS date,
            CASE
                WHEN substr(the_time,2,1) = ':' AND instr(the_time,' ') = 4 AND instr(the_time,' am') 
                    THEN '0'||substr(the_time,1,1)||':0'||substr(the_time,3,1)
                WHEN substr(the_time,2,1) = ':' AND instr(the_time,' ') = 5 AND instr(the_time,' am') 
                    THEN '0'||substr(the_time,1,1)||':'||substr(the_time,3,2)   
                WHEN substr(the_time,2,1) = ':' AND instr(the_time,' ') = 4 AND instr(the_time,' pm') 
                    THEN CAST(12 + CAST(substr(the_time,1,1) AS INTEGER) AS TEXT)||':0'||substr(the_time,3,1)
                WHEN substr(the_time,2,1) = ':' AND instr(the_time,' ') = 5 AND instr(the_time,' pm') 
                    THEN CAST(12 + CAST(substr(the_time,1,1) AS INTEGER) AS TEXT)||':'||substr(the_time,3,2)        
                WHEN substr(the_time,3,1) = ':' AND instr(the_time,' ') = 5 AND instr(the_time,' am') 
                    THEN substr(the_time,1,2)||':0'||substr(the_time,4,1)
                WHEN substr(the_time,3,1) = ':' AND instr(the_time,' ') = 6 AND instr(the_time,' am') 
                    THEN substr(the_time,1,2)||':'||substr(the_time,4,2)        
                WHEN substr(the_time,3,1) = ':' AND instr(the_time,' ') = 5 AND instr(the_time,' pm') 
                    THEN CAST(12 + CAST(substr(the_time,1,2) AS INTEGER) AS TEXT)||':0'||substr(the_time,4,1)
                WHEN substr(the_time,3,1) = ':' AND instr(the_time,' ') = 6 AND instr(the_time,' pm') 
                    THEN CAST(12 + CAST(substr(the_time,1,2) AS INTEGER) AS TEXT)||':'||substr(the_time,4,2)
            END AS time
        FROM mytable 
        )
UPDATE mytable 
    SET 
        the_date = (SELECT date||' '||time FROM cte1 WHERE cte1id = mytable.rowid),
        the_time = (SELECT date||' '||time FROM cte1 WHERE cte1id = mytable.rowid)
;

下面显示了查询变得简单了多少,另外如何从转换后的表中检索接近原始格式的日期和时间(时间不是pm):-

SELECT 
    strftime('%d-%m-%Y %H:%M',the_date) AS old_format, -- Close to original format
    * FROM mytable ORDER BY the_date DESC; -- much simpler to sort

结果是:-

enter image description here

  • old_format 是接近原始格式(但24小时)的日期
  • 可以看出, the_date the_time 列已转换为YYYY-MM-DD HH:MM格式,因此,最先排序的排序方式很简单可以按列(任一)按降序排序。
  • 使用这种格式选择日期范围也非常简单。 WHERE the_date BETWEEN '2019-01-01' AND '2019-03-31'仅选择2019年前3个月的3行(从上述行中)。