【问题标题】:Ordering of Dates and retrieving results based on current date (Birth Day List) SQLite基于当前日期的日期排序和检索结果(生日列表)SQLite
【发布时间】:2013-12-02 04:34:30
【问题描述】:

我有一个日期作为字符串存储在 Sqlite 列中,格式为 YYYY-MM-DD (年日期和月份未分成三列)现在我需要进行查询,该查询为我提供结果最接近查询日期的日期作为第一个条目,并且顺序按升序进行。这里我对年份不感兴趣,只有月份和日期很重要。根据我的要求,我应该处理什么类型的查询,以便按顺序获得这些日期。

例子:

我有日期

1980-01-11, 1999-08-03, 2013-12-03 查询后我应该得到:(基于当前日期,考虑到它是 2013 年 12 月 1 日)

2013-12-03,1999-01-11,1980-08-03(仅按月和日排序)。

我也从这里参考了:MySQL query to sort upcoming birthdays based on current date 但不是很清楚。我认为 Unix 时间戳作为存储在日期列中的长值将有助于我感兴趣的查询类型,而不是简单的日期格式。

【问题讨论】:

  • 只有月份和日期?所以如果查询的输入日期是XXXX-07-01,那么结果中的最后一个日期应该是XXXX-01-01(当然如果存在的话)?
  • 完全依赖于当前日期,比如XXXX-31-12,查询结果的第一个日期应该是XXXX-01-01。
  • 请解释否决票?我很想改进。
  • 我认为反对票与您没有进行任何试验有关。无论如何,日期处理有点奇怪,因为它就像周期一样,因为你可以从给定日期(我知道,今天,但可以是任何日期)最远的是半年
  • 这就是创建 SO 的原因,我想要一个标题并且没有要求任何人做我的功课。

标签: android sqlite date


【解决方案1】:

以下就可以了:

SELECT *
FROM _table
ORDER BY SUBSTR(DATE('NOW'), 6)>SUBSTR(birthdate, 6), SUBSTR(birthdate, 6)

查看SQL Fiddle

SUBSTR(date, 6) 将从日期中删除年份部分。生日必须按MM-DD 排序,但首先应显示今天之后发生的,然后是今天之前发生的。

SUBSTR(DATE('NOW'), 6)>SUBSTR(birthdate, 6) 将返回 0 表示生日 MM-DD 大于或等于今天 MM-DD,否则返回 1。因此,第一个表达式将 ORDER comming date 之后的过去日期。第二个参数只是ORDER 日期MM-DD

SQL Fiddle中逐步查看。

【讨论】:

  • 工作完美,但那里发生了什么?数据库查询是我在大学时最薄弱的科目。
  • 如果我也想考虑 Year 部分怎么办?在生日列表的上下文中?
  • 什么意思?也按年份排序?只需将, birthdate 附加到ORDER BY 子句即可。
【解决方案2】:

有很多方法可以做到这一点,有些方法比其他方法更有效。我将建议一个无需更改数据库格式即可有效的解决方案,但请注意,如果您可以使用单独的年、月、日整数列,或者一个 unix 时间戳列。

select *, 
strftime('%j', 
    strftime('%Y', 'now') || '-' || 
    strftime('%m', birthday) || '-' || 
    strftime('%d', birthday)
)
- strftime('%j', 
    strftime('%Y', 'now') || '-' || 
    strftime('%m', 'now') || '-' || 
    strftime('%d', 'now')
)
as daydiff
from users
where daydiff >=0

union all

select *, 
strftime('%j', 
    strftime('%Y', 'now') || '-' || 
    strftime('%m', birthday) || '-' || 
    strftime('%d', birthday)
)
- strftime('%j', 
    strftime('%Y', 'now','+1 year') || '-' || 
    strftime('%m', 'now') || '-' || 
    strftime('%d', 'now')
) + 366
as daydiff
from users
where daydiff <366
order by daydiff

上面使用今天的年份和每个用户的月份和日期部分来计算一年中的某天(例如,今天 2013 年 12 月 11 日是第 345 天)并减去今天的日期。当前年份发生的生日将具有 >= 0 的 daydiff 值,因此我们首先使用它们。这是union 的第一部分。

第二部分进行相同的计算,但对于那些生日是明年的人,所以我们将 366 添加到 daydiff 值,并确保我们只得到第一部分没有得到的字段。

可以用CASE WHEN 代替union 重写相同的查询。 CASE 替代方案会更快,因为它只会从 users 表中获取行一次,而不是两次,但在这个论坛上写对我来说真的很难看。再想一想,我还是写吧,因为它更快

select *, 
CASE WHEN 
  strftime('%j', 
    strftime('%Y', 'now') || '-' || strftime('%m', birthday) || '-' || strftime('%d', birthday)
  )
  - strftime('%j', 
    strftime('%Y', 'now') || '-' || strftime('%m', 'now') || '-' || strftime('%d', 'now')
  ) >= 0
THEN 
  strftime('%j', 
    strftime('%Y', 'now') || '-' || strftime('%m', birthday) || '-' || strftime('%d', birthday)
  )
  - strftime('%j', 
    strftime('%Y', 'now') || '-' || strftime('%m', 'now') || '-' || strftime('%d', 'now')
  ) 
ELSE 
  strftime('%j', 
    strftime('%Y', 'now') || '-' || strftime('%m', birthday) || '-' || strftime('%d', birthday)
  )
  - strftime('%j', 
    strftime('%Y', 'now') || '-' || strftime('%m', 'now') || '-' || strftime('%d', 'now')
  ) + 366 
END
as daydiff
from users
order by daydiff

也是最后一点。我在明年的生日手动添加 366,但正确的做法是根据年份(365 或 366)添加一年中的天数。由于我们只需要它来订购,这不会造成麻烦,因为最坏的情况是它将为所有明年的用户添加一个到 daydiff。因此,“2013-12-31”的生日将给出 daydiff=20,但“2014-01-01”的生日将给出 daydiff=22。

编辑:

这是fiddle

【讨论】:

  • 哇!很好的解释我都试过了,像魅力一样工作!
猜你喜欢
  • 1970-01-01
  • 2013-03-18
  • 1970-01-01
  • 2020-06-01
  • 1970-01-01
  • 2019-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多