我有一个表“用户”列“date_of_birth”(DATE格式与日,月,年)。 在前端,我需要列出5个即将到来的生日。如何在Rails中创建“即将到来的生日”模块?
花了年龄试图找出逻辑..也浏览在谷歌没有运气每一个可能的文章..
任何建议,如何做到这一点的回报率?
谢谢!
我有一个表“用户”列“date_of_birth”(DATE格式与日,月,年)。 在前端,我需要列出5个即将到来的生日。如何在Rails中创建“即将到来的生日”模块?
花了年龄试图找出逻辑..也浏览在谷歌没有运气每一个可能的文章..
任何建议,如何做到这一点的回报率?
谢谢!
几个答案建议计算/存储年的一天并对其进行排序,但当靠近年底并需要考虑生日中的人时,这本身并不会很好。明年初。
我想找一个解决方案,你可以计算每个人的下一个生日的完整日期(年,月,日),然后对其进行排序。您可以在Ruby代码中执行此操作,也可以在数据库中使用存储过程。后者会更快,但会让你的应用更难以在以后迁移到不同的数据库平台。
只需每天更新一次即将到来的生日的列表就可以了,这意味着您可以使用某种形式的缓存。因此,需要查询/代码的速度是不成问题的,而且这样的事情应该可以正常工作,只要你缓存结果:
class User
def next_birthday
year = Date.today.year
mmdd = date_of_birth.strftime('%m%d')
year += 1 if mmdd < Date.today.strftime('%m%d')
mmdd = '0301' if mmdd == '0229' && !Date.parse("#{year}0101").leap?
return Date.parse("#{year}#{mmdd}")
end
end
users = User.find(:all, :select => 'id, date_of_birth').sort_by(&:next_birthday).first(5)
编辑:固定到闰年正常工作。
我会有一个before_save回调函数,用于计算并存储数据库中一年中的某天以及生日。
然后你有一个简单的查询来拉回接下来的5个生日。确保处理年底的边界条件(我会检查你是否在RoR中得到5个结果,然后在1月1日运行一个新的查询以获得一些额外的生日来弥补它到5)。
您可能需要缓存结果,以便在查询不在公共页面时继续重新运行查询。
我也认为今年的日子将是一段路要走,但事实上,一年中的大部分时间都有所不同,这取决于它是否是闰年,这使得它很棘手。
更好的方法是将月份和日期存储为字符串:d.strftime('%m%d')。然后,您可以使用它作为(可能)两个查询(假设新栏是“MONTHDAY”)
首先,
User.find(:all,
:condition => [:monthday > Date.now.strftime('%m%d')],
:select => "DISTINCT monthday",
:limit => 5)
如果你没有得到5个结果,再次进行查询,除使用“ 0101“而不是日期计算并降低限制。
这会让你得到一个monthday
字符串列表,然后你必须回到日期。
如果您想要用户,请删除:select
行。
Rich_s对before_save的评论是如何计算字符串 – 2009-06-29 02:16:03
如果您使用的是Oracle,您可以在不创建新列的情况下执行此操作。国际海事组织这是一种气味来创建一个包含您已有数据的列。
这个SQL有点难看 - 我确定有一个更优雅的方法来做到这一点。通常在这些情况下,我会问我的DBA朋友的建议。
User.find(:all,
:conditions =>
"TO_NUMBER(TO_CHAR(dob, 'MMDD')) >= TO_NUMBER(TO_CHAR(SYSDATE, 'MMDD'))",
:order => "TO_NUMBER(TO_CHAR(dob, 'MMDD'))",
:limit => 5)
有些人认为重复的列速度较快,但如果你有足够的用户数据速度是一个问题,您应该基准对没有它的表中有TO_NUMBER(TO_CHAR(dob, 'MMDD'))
函数索引的重复列。
这是如何工作的当年的最后几天与同一年剩余5人的生日相比较少? – 2009-06-29 04:19:10
以下是我发现今天的生日:
User.find_by_sql("select * from users where date_format(date_of_birth, '%m%d') = date_format(now(), '%m%d')"
)
我每天运行一次。它从大约100,000行不到一秒钟。 (它不妥善处理出生于2月29日的人)
由于这篇文章在我的Rails应用程序3,我使用:
u = User.where("strftime('%m%d', date_of_birth) = ?", Date.today.strftime('%m%d'))
更新:
要在PostgreSQL使用:
u = User.where("extract(month from date_of_birth) = ? AND extract(day from date_of_birth) = ?", Date.today.strftime('%m'), Date.today.strftime('%d'))
这是更好地使用SQL,使这个查询:
next_month = (Date.today + 1.month).month # or use any other integer
users_having_birhtday_next_month =
User.where("EXTRACT(MONTH FROM date_of_birth) = ?", next_month)
注:EXTRACT - PostgreSQL的功能
如果你的数据库是MySQL的,下面是可能更快:
scope :birthday_next_week, (lambda {
where('DayOfYear(date_of_birth) >= 7
And DayOfYear(date_of_birth) - DayOfYear(curdate()) Between 0 and 6) Or
(MOD(YEAR(curDate()),4) = 0) And MOD(YEAR(curDate()),100) != 0
And (DayOfYear(date_of_birth) + 366 - DayOfYear(curdate())) % 366 < 7) Or
(DayOfYear(date_of_birth) + 365 - DayOfYear(curdate())) % 365 < 7').
order('DATE_FORMAT(date_of_birth, "%m-%d") ASC')
})
编辑:改变使其在一周前的除夕/飞跃工作年份。
什么是数据库?如果答案是在那里做,它会有所作为 – 2009-06-29 00:38:13
Kathy - 我会说在RoR模型中做,并避免任何数据库特定的SQL – RichH 2009-06-29 01:48:16