问题描述
我想通过连接计划表和交易表使用MysqL interval函数在交易日期中添加月份,但是此方法不起作用,但是如果我以静态方式在交易日期中添加月份,则该方法有效。
const deferredRec = step => {
while (step && step.tag === "Call")
step = step.f(...step.args);
return step;
};
const Call = f => (...args) =>
({tag: "Call",f,args});
const record = (type,o) =>
(o[type.name || type] = type.name || type,o);
const thisify = f => f({});
const arrFold = f => init => xs => {
let acc = init;
for (let i = 0; i < xs.length; i++)
acc = f(acc) (xs[i],i);
return acc;
};
const Task = task => record(
Task,thisify(o => {
o.task = (res,rej) =>
task(x => {
o.task = k => k(x);
return res(x);
},rej);
return o;
}));
const taskMap = f => tx =>
Task((res,rej) =>
Call(f => tx.task(f)) (x => Call(res) (f(x)),rej));
const taskOf = x =>
Task((res,rej) => res(x));
const taskAnd = tx => ty =>
Task((res,rej) =>
tx.task(x =>
ty.task(y =>
res([x,y]),rej),rej));
const taskAll =
arrFold(tx => ty =>
taskMap(([xs,x]) =>
xs.concat([x]))
(taskAnd(tx) (ty)))
(taskOf([]));
const inc = x =>
Task((res,rej) =>
setTimeout(x => deferredRec(res(x + 1)),x)); // A
const xs = Array(1e4).fill(inc(0));
const main = taskAll(xs);
deferredRec(main.task(console.log,console.error));
表:
plan
plan_id plan
1 6 month
2 12 month
3 3 month
表:
transaction
MySQL查询(不起作用):
id user_id subscribed_on plan_id
1 2 2020-04-04 1
2 4 2019-02-22 2
如果我以静态方式添加月份,则工作正常:
SELECT t.* FROM transaction t inner join plan p on p.plan_id=t.plan_id
where t.user_id=2 and DATE_ADD(date(t.subscribed_on),INTERVAL p.plan) >= CURDATE()
order by t.id desc
解决方法
不幸的是,数据中的字符串不等于间隔。一种方法是:
date(t.subscribed_on) + interval substring_index(plan,' ') + 0 month
请注意,month
是关键字,而不是字符串。
MySQL不支持那样使用间隔。与其他数据库(例如Postgres)不同,unit参数是关键字,而不是文字字符串。
我怀疑您的表可能会存储其他间隔,而不仅仅是几个月(例如,几年,几天等等)。如果是这样,您可以使用字符串函数和case
表达式来容纳不同的可能值,例如:
select t.*
from transaction t
inner join plan p on p.plan_id = t.plan_id
where
t.user_id = 2
and date(t.subscribed_on) + case substring_index(p.plan,' ',-1)
when 'year' then interval substring_index(p.plan,1) year
when 'month' then interval substring_index(p.plan,1) month
when 'day' then interval substring_index(p.plan,1) day
end
>= current_date
order by t.id desc
这里的逻辑是将存储的间隔字符串分为两部分:数字和单位; case
表达式处理单位并相应地生成正确的文字间隔。
尝试将plan
表中的plan
列强制为整数。似乎无法将字符串强制转换为间隔。
我尝试过这样:
WITH
plan( plan_id,plan) AS (
SELECT 1,'6 month'
UNION ALL SELECT 2,'12 month'
UNION ALL SELECT 3,'3 month'
),transaction(id,user_id,subscribed_on,plan_id) AS (
SELECT 1,2,DATE '2020-09-04',1
UNION ALL SELECT 2,4,DATE '2019-02-22',2
)
SELECT t.*
FROM transaction t
INNER JOIN plan p ON p.plan_id = t.plan_id
WHERE t.user_id = 2
AND DATE_ADD(
DATE(t.subscribed_on),INTERVAL CAST(REPLACE(plan,' month','') AS SIGNED) MONTH
) >= CURDATE()
ORDER BY t.id DESC
(不返回任何结果,因为您的示例数据中没有足够高的日期...)