我有一张周年纪念日的桌子。我想要一个查询,它会在接下来的10天内返回一系列纪念日。例如:
birthdate
---------
1965-10-10
1982-05-25
SELECT birthdate FROM Anniversaries WHERE mystical_magical_mumbo_jumbo <= 10
+------------+
| birthdate |
+------------+
| 1982-05-25 |
+------------+
1 row in set (0.01 sec)
我想以x <= 10
的形式保存查询,因为我会在查询的其他部分使用该数字10,如果我将其设置为变量,我可以在任何地方更改它通过更改变量,而不必重新编写查询。
答案 0 :(得分:7)
正如其他人所说,你需要忽略比较中的年份。 DAYOFYEAR()函数是一种方法。
这是我头脑中的快速解决方案。它将在接下来的10天内返回所有生日,即使是12月下旬和生日是明年。
它没有正确处理闰年,因此如果今年是闰年并且该人不是在闰年出生,反之亦然,那么3月初生日将会停止1天。闰年也将导致1月初的生日有时在12月下旬出现休息一天。如果有人想添加闰年修正,请随意:)
SELECT birthdate
FROM Anniversaries
WHERE dayofyear(birthdate) - dayofyear(curdate()) between 0 and 10
or dayofyear(birthdate) + 365 - dayofyear(curdate()) between 0 and 10;
答案 1 :(得分:1)
试试这个
SELECT birthdate FROM Anniversaries
WHERE DATEDIFF(CURTIME(),birthdate) >= 0
AND DATEDIFF(CURTIME(),birthdate) <= 10
选中此项以获取参考MySQL DATEDIFF
DATEDIFF(表达式1,表达式2)
DATEDIFF()返回expr1 - expr2,表示为从一个日期到另一个日期的天数值。 expr1和expr2是日期或日期和时间表达式。在计算中仅使用值的日期部分。
的MySQL&GT; SELECT DATEDIFF('2007-12-31 23:59:59','2007-12-30'); - &GT; 1
的MySQL&GT; SELECT DATEDIFF('2010-11-30 23:59:59','2010-12-31'); - &GT; -31
答案 2 :(得分:1)
我们想要实现的是在最近的日期范围内发生的周年纪念清单。 为实现这一目标并适应翻转,我们需要生成一份涵盖日期范围的所有周年纪念日清单。 我使用的解决方案产生了去年,今年和明年的周年纪念记录 并仅输出属于给定日期范围内的那些记录。联合查询如下所示:
SELECT Date_Add(birth_date,INTERVAL (Year(now())-Year(birth_date)-1) YEAR) as dt,
FROM Anniversaries
WHERE Date_Add(birth_date,INTERVAL (Year(now())-Year(Date)-1) YEAR)
BETWEEN Date_sub(now(), INTERVAL 7 Day) AND Date_add(now(), INTERVAL 21 Day)
UNION
SELECT Date_Add(birth_date,INTERVAL (Year(now())-Year(birth_date)) YEAR) as dt,
FROM Anniversaries
WHERE Date_Add(birth_date,INTERVAL (Year(now())-Year(Date)) YEAR)
BETWEEN Date_sub(now(), INTERVAL 7 Day) AND Date_add(now(), INTERVAL 21 Day)
UNION
SELECT Date_Add(birth_date,INTERVAL (Year(now())-Year(birth_date)+1) YEAR) as dt,
FROM Anniversaries
WHERE Date_Add(birth_date,INTERVAL (Year(now())-Year(Date)+1) YEAR)
BETWEEN Date_sub(now(), INTERVAL 7 Day) AND Date_add(now(), INTERVAL 21 Day)
ORDER BY dt
第一个SELECT语句将所有日期递增到去年,并选择属于所提供日期范围的任何项目 下一个SELECT语句将所有日期递增到当前年份,并选择属于所提供日期范围的所有项目 最后一个SELECT语句将所有日期递增到明年,并选择属于所提供日期范围的任何项目 最后,按日期排序。
你有它。这将在给定时期内可靠地选择纪念日。如果需要更长的时间, 可能需要生成其他SELECT语句并将它们与UNION连接。 我修改了我的代码以匹配上面的示例,但自修改以来没有对其进行测试。
答案 3 :(得分:0)
如果您将生日与生日分开存储,则实际上可以使用索引。生日列会有年份和月份,但都会有同一年(例如2000年)。
然后你会这样做你的查询:
SELECT birthdate
FROM Anniversaries
WHERE birthday >= DATE_ADD(MAKEDATE(2000, DAYOFYEAR(CURDATE())), INTERVAL 10 DAYS)
虽然表达式并不完全符合您的要求,但数字10仍位于表达式的右侧。将函数应用于表达式的右侧并仅保留表达式左侧的列允许MySQL使用生日列上的索引(假设您有索引)。
答案 4 :(得分:0)
根据alejandrobog的回答:
SELECT birthdate FROM Anniversaries
WHERE DATEDIFF(MAKEDATE(YEAR(CURRENT_DATE()), DAYOFYEAR(birthdate), CURRENT_DATE()) >= 0
AND DATEDIFF(MAKEDATE(YEAR(CURRENT_DATE()), DAYOFYEAR(birthdate), CURRENT_DATE()) <= 10
答案 5 :(得分:0)
MAKEDATE()
创建一年中的日期和一年中的某一天,因此我可以用它来画出旧年份:
SELECT
anniversary
, MAKEDATE( YEAR(NOW()), DAYOFYEAR(anniversary) ) AS thisyear
FROM Anniversaries;
+-------------+-------------+
| anniversary | thisyear |
+-------------+-------------+
| 1978-07-29 | 2010-07-29 |
| 1959-04-17 | 2010-04-17 |
+-------------+-------------+
然后我可以使用DATEDIFF()
计算直到(或从那时)的日期:
SELECT
anniversary
, MAKEDATE( YEAR(NOW()), DAYOFYEAR(anniversary) ) AS thisyear
, DATEDIFF( MAKEDATE(YEAR(NOW()),DAYOFYEAR(anniversary)), NOW()) as days
FROM Anniversaries;
+-------------+-------------+------+
| anniversary | thisyear | days |
+-------------+-------------+------+
| 1978-07-29 | 2010-07-29 | 70 |
| 1959-04-17 | 2010-04-17 | -33 |
+-------------+-------------+------+
假设NOW()是5/20。
修改,以便上述内容在年度翻转时无效。一种解决方案是添加另一个计算,其中周年纪念日是明年。在这里,我对日期“2010-12-31”进行了硬编码,并在OR
子句中使用HAVING
来过滤与今年或下一年匹配的天数:
SELECT birth_date
, MAKEDATE(YEAR('2010-12-31'),DAYOFYEAR(birth_date)) as anniversary
, DATEDIFF( MAKEDATE(YEAR('2010-12-31'),DAYOFYEAR(birth_date)), '2010-12-31') as days
, MAKEDATE(YEAR(NOW())+ 1,DAYOFYEAR(birth_date)) as next_anniversary
, DATEDIFF( MAKEDATE(YEAR(NOW())+ 1,DAYOFYEAR(birth_date)), '2010-12-31') as next_days
FROM Anniversaries
HAVING ( ( days <= 25 AND days > 0 ) OR next_days <= 25 );
+------------+-------------+------+------------------+-----------+
| birth_date | anniversary | days | next_anniversary | next_days |
+------------+-------------+------+------------------+-----------+
| 2010-01-23 | 2010-01-23 | -342 | 2011-01-23 | 23 |
| 1975-01-11 | 2010-01-11 | -354 | 2011-01-11 | 11 |
+------------+-------------+------+------------------+-----------+
2 rows in set (0.00 sec)
答案 6 :(得分:0)
SELECT firstName, lastName, DOB, if( (
datediff( date( concat( year( current_date ) , '-', month( DOB ) , '-', day( DOB ) ) ) , current_date ) ) >=0, (
datediff( date( concat( year( current_date ) , '-', month( DOB ) , '-', day( DOB ) ) ) , current_date )),
datediff( date( concat( year( current_date ) +1, '-', month( DOB ) , '-', day( DOB ) ) ) , current_date )
)DAYSTOBDAY
FROM birthinfo
WHERE (
if( (
datediff( date( concat( year( current_date ) , '-', month( DOB ) , '-', day( DOB ) ) ) , current_date ) ) >=0, (
datediff( date( concat( year( current_date ) , '-', month( DOB ) , '-', day( DOB ) ) ) , current_date )),
datediff( date( concat( year( current_date ) +1, '-', month( DOB ) , '-', day( DOB ) ) ) , current_date )
)
)
BETWEEN 0
AND 31
firstName lastName DOB DAYSTOBDAY
Michelle Smith 1979-04-16 17
Kirsten Dunst 1982-04-30 31
它远不是一个“好”的答案,它不是很有趣,但是在我的头脑中起作用。实现你想要的。 我创建了一个带有firstname,lastname和DOB的表,当然你可以直接替换它。