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