从ACCESS转为MSSQL2005后,遇到一个闰年2000-2-29日期问题。
sql="select count(*) as ttshu from shengri where (user="&session("user")&" and gongnong=0 and DateDiff(day,getdate(),dateadd(year,DateDiff(year,birthday,getdate()),birthday))between 0 and 14) or (user="&session("user")&" and gongnong=1 and shengrin<>'2-29' and shengrin<>'2-30' and DateDiff(day,'"&(jinnongli)&"',dateadd(year,DateDiff(year,nongli,'"&(jinnongli)&"'),nongli))between 0 and 14)"
nongli
2000-2-29
1990-4-11
1988-5-18
shengrin
gongnong=0 表示公历
gongnong=1 表示农历
birthday 表示公历生日
nongli 表示农历生日
通过上面语句列出14天内过阳历生日和农历生日的人数,在ACCESS运行正常,转为MSSQL数据库就出错了。语句里的字段nongli,其中一条数据是2000-2-29,
运行 提示
[SQL Server]将 expression 转换为数据类型 datetime 时出现算术溢出错误。
由此发现MSSQL2005不识别2-29 2-30,当把上述2000-2-29改为2000-2-28运行就正常了。
但是有用户提交的生日是2000-2-29,请教风云怎么做,能修改上面的语句避免错误吗

2023/11/24 9:32:27

IP:已设置保密
如果改成了2-28入库,当快过生日时或生日当天,数据库有其他人提交的不同生日
1. 我要列出最近14天过生日的人数,怎么处理呢,
2. 以及在过生日的时候,提前几天或当天给用户发邮件提醒,怎么处理呢。

2023/11/24 9:51:20

IP:已设置保密
那要看实际情况,例如今年没有 2月29,那这个人今年的生日算 2月28?还是 3月1日?还是今年不过生日?😀
也可以尝试使用 case when,遇到 2-29 且 year % 4 > 0 的情况就转为 2-28。
select convert(date, year(getdate()) + '-' + case when shengri when '2-29' and year(getdate()) % 4 > 0 then shengri else '2-28' end)

2023/11/24 9:55:30

IP:已设置保密
sql="select count(*) as ttshu from shengri where (user="&session("user")&" and gongnong=0 and DateDiff(day,getdate(),dateadd(year,DateDiff(year,birthday,getdate()),birthday))between 0 and 14) or (user="&session("user")&" and gongnong=1 and shengrin<>'2-29' and shengrin<>'2-30' and DateDiff(day,'"&(jinnongli)&"',dateadd(year,DateDiff(year,nongli,'"&(jinnongli)&"'),nongli))between 0 and 14)"
没有2-29 2-30,生日也只能28的过(也即提前1天过)。当有2-29 2-30,那就正常过啊。
风云,请教具体语句应该怎么写呢?

2023/11/24 10:07:26

IP:已设置保密
我没看懂这个怎么判断农历生日的。如果只判断公历生日,我会这么写(PGSQL):
with shengri as (
select '2-19' shengrin union
select '3-1' union
select '2-28' union
select '11-28'
today as (
select extract(year from now()) toyear, current_date today
-- 转换成日期格式
shengri1 as (
select (toyear || '-' || case when shengrin='2-29' and toyear % 4 > 0 then '2-28' else shengrin end)::date shengrin
from today a, shengri b
-- 小于今天的都+1年
shengri2 as (
select case when shengrin<current_date then shengrin + interval '1 Year' else shengrin end::date shengrin from shengri1
select shengrin from shengri2 where shengrin-current_date<15

2023/11/24 10:32:11

IP:已设置保密
去掉注释和换行,改成 SQL 可以试试这个:
with shengri as (select '2-19' shengrin union select '3-1' union select '2-28' union select '11-28'), today as (select year(getdate()) toyear, convert(date, getdate()) today), shengri1 as (select a.today, concat(toyear, '-', case when shengrin='2-29' and toyear % 4 > 0 then '2-28' else shengrin end) shengrin from today a, shengri b), shengri2 as (select convert(date, case when shengrin<today then dateadd(year, 1, shengrin) else shengrin end) shengrin, today from shengri1) select shengrin, datediff(day, today, shengrin) remain from shengri2 where datediff(day, today, shengrin)<15

2023/11/24 10:50:59

IP:已设置保密
,today as (select year(getdate()) toyear, convert(date, getdate()) today)
,shengri1 as (select a.today, concat(toyear, '-', case when shengrin='2-29' and toyear % 4 > 0 then '2-28' else shengrin end) shengrin from today a, shengri b)
,shengri2 as (select convert(date, case when shengrin<today then dateadd(year, 1, shengrin) else shengrin end) shengrin, today from shengri1)
select shengrin, datediff(day, today, shengrin) remain from shengri2 -- where datediff(day, today, shengrin)<15结果为:
+------------+--------+
| shengrin | remain |
+------------+--------+
| 2024-02-19 | 86 |
| 2024-03-01 | 96 |
| 2024-02-28 | 93 |
| 2023-11-28 | 4 |
+------------+--------+

2023/11/24 10:52:04

IP:已设置保密
放进ASP文件里面查询,如下面:
sql="select count(*) as ttshu from shengri where (user="&session("user")&" and gongnong=0 and DateDiff(day,getdate(),dateadd(year,DateDiff(year,birthday,getdate()),birthday))between 0 and 14) or (user="&session("user")&" and gongnong=1 and shengrin<>'2-29' and shengrin<>'2-30' and DateDiff(day,'"&(jinnongli)&"',dateadd(year,DateDiff(year,nongli,'"&(jinnongli)&"'),nongli))between 0 and 14)"
你写的代码可以整合到上面的语句里面吗?

2023/11/24 11:51:41

IP:已设置保密
asp 也可以直接执行这个 SQL 语句的。写多行是为了看得更清晰。你可以试试
sql = "with shengri as (select '2-19' shengrin union select '3-1' union select '2-28' union select '11-28'), today as (select year(getdate()) toyear, convert(date, getdate()) today), shengri1 as (select a.today, concat(toyear, '-', case when shengrin='2-29' and toyear % 4 > 0 then '2-28' else shengrin end) shengrin from today a, shengri b), shengri2 as (select convert(date, case when shengrin<today then dateadd(year, 1, shengrin) else shengrin end) shengrin, today from shengri1) select shengrin, datediff(day, today, shengrin) remain from shengri2 where datediff(day, today, shengrin)<15"
set Rs = Conn.Execute sql
从你的 SQL 语句来看,你的逻辑和结构有些复杂,我可能会这么处理:
1、计算今天农历和公历的日期差值,然后农历统一增加该差值。
2、统一格式,将农历的 YYYY-MM-DD 统一为 MM-DD 结构。
3、将生日全部设置为今年。对小于今天的日期再增加1年
4、筛选 between today and dateadd(day, today, 14) 的数据即可
具体如何写,我这没有条件测试,你可以尝试按照该逻辑编写 SQL 语句。然后你的SQL 语句应该是查看某个用户是否在 14 天内过生日,不是列出所有 14 天内即将过生日的人。

2023/11/24 12:02:35

IP:已设置保密