我正在尝试整理一个结果集,该结果集为按即将到来的生日排序的5个最近的用户排序。这种方法非常有效,直到闰年发挥作用。例如:
最重要的结果是1987年出生,而较低的是1988年。 u_birth存储为yyyy-mm-dd。 是否有一种简单的方法可以对此问题进行排序而无需重写整个查询?
SELECT u_birth, IF( DAYOFYEAR( u_birth ) >= DAYOFYEAR( NOW() ),
DAYOFYEAR( u_birth ) - DAYOFYEAR( NOW() ),
DAYOFYEAR( u_birth ) - DAYOFYEAR( NOW() ) +
DAYOFYEAR( CONCAT( YEAR( NOW() ), '-12-31' ) )
)
AS distance
FROM (blog_users)
WHERE `s_agehide` = 0
ORDER BY distance ASC
LIMIT 5
此查询是从mysql手册中获取并修改的:http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#c7489
答案 0 :(得分:8)
如果您的算法取决于该人的出生年份,则显然存在问题。要解决此问题,首先在当前日期之后找到每个人的下一个生日,然后计算该日期与现在之间的差异。
SELECT u_birth, DATEDIFF(next_birthday, NOW()) AS distance FROM (
SELECT *, ADDDATE(birthday, INTERVAL birthday < DATE(NOW()) YEAR) AS next_birthday
FROM (
SELECT *, ADDDATE(u_birth, INTERVAL YEAR(NOW()) - YEAR(u_birth) YEAR) AS birthday
FROM blog_users
WHERE s_agehide = 0
) AS T1
) AS T2
ORDER BY distance ASC
LIMIT 5
结果:
'1992-02-29', 20
'1993-03-01', 21
'1987-05-15', 96
'1988-05-15', 96
'1988-09-18', 222
测试数据:
CREATE TABLE blog_users (u_birth NVARCHAR(100) NOT NULL, s_agehide INT NOT NULL);
INSERT INTO blog_users (u_birth, s_agehide) VALUES
('1987-05-15', 0),
('1988-05-15', 0),
('1988-09-20', 0),
('2000-01-02', 0),
('2000-01-03', 1),
('1988-09-19', 0),
('1988-09-18', 0),
('1992-02-29', 0),
('1993-03-01', 0);
请注意,在闰日出生的人假定在非闰年有2月28日的生日。
此外,您的查询不包含用户的用户ID。你可能想要添加它,我想。
答案 1 :(得分:2)
SELECT
CONCAT(
YEAR(CURRENT_DATE()),
'-',
DATE_FORMAT((birthDate),
'%m-%d'
)
),
fullName
FROM
employees
WHERE
birthDate != 0
AND(
CONCAT(
YEAR(CURRENT_DATE())+ 1,
'-',
DATE_FORMAT((birthDate),
'%m-%d'
)
)BETWEEN CURRENT_DATE()
AND DATE_ADD(
CURRENT_DATE(),
INTERVAL 21 DAY
)
OR CONCAT(
YEAR(CURRENT_DATE()),
'-',
DATE_FORMAT((birthDate),
'%m-%d'
)
)BETWEEN CURRENT_DATE()
AND DATE_ADD(
CURRENT_DATE(),
INTERVAL 21 DAY
)
)
ps: birthDate 是我存储员工出生日期的列。 员工是表名。
答案 2 :(得分:1)
2月29日之后的闰年比平常更进一步,不要使用dayofyear
。相反,提取月和日,并将它们与今天的年份结合在一起。然后做比较。
像这样:
SELECT u_birth,
IF(DATE(CONCAT(YEAR(NOW()),'-',MONTH(u_birth),'-',DAY(u-birth))) >= DATE(NOW()),
...
ETA:
因此我不必重写用于将出生日期转换为生日的表达式,我会将其粘贴在变量中。我建议您编写一个执行转换的函数,以便您可以直接在查询中使用它。
SET @birthday= SELECT DATE(CONCAT(YEAR(NOW()),'-',MONTH(u_birth),'-',DAY(u-birth))) FROM users WHERE user_id=x; //obviously only good for one value, but use the example for the calculation
SELECT u_birth,
IF(DATE(@birthday)>=DATE(NOW()),
DATEDIFF(DATE_ADD(@birthday, INTERVAL 1 YEAR),NOW()),
DATEDIFF(NOW(),@birthday)
) as days
FROM users WHERE user_id=x;
答案 3 :(得分:1)
也许有人会受到这种代码和平的启发。
它在我的案例中完美地运作但我认为有很多日期计算...
SELECT CONCAT(YEAR(CURRENT_DATE()),'-',DATE_FORMAT( FROM_UNIXTIME(date_of_birth), '%m-%d' )), fe_users.*
FROM `fe_users`
WHERE `date_of_birth` != 0 AND (
CONCAT(YEAR(CURRENT_DATE())+1,'-',DATE_FORMAT( FROM_UNIXTIME(date_of_birth), '%m-%d' )) BETWEEN CURRENT_DATE() AND DATE_ADD(CURRENT_DATE(), INTERVAL 7 DAY)
OR
CONCAT(YEAR(CURRENT_DATE()),'-',DATE_FORMAT( FROM_UNIXTIME(date_of_birth), '%m-%d' )) BETWEEN CURRENT_DATE() AND DATE_ADD(CURRENT_DATE(), INTERVAL 7 DAY)
)
通过SQL-Code的这种和平,您将获得表fe_users的所有用户,其date_of_birth(保存为unix-timestamp)将在接下来的7天内。您可以通过更改date_add()函数使用的时间间隔,将其扩展为21天。