在perl中,我有以下数据库查询:
my $list = $db->SelectARef("SELECT p.*, u.usr_login, u.usr_money, u.usr_email, u.usr_pay_email, u.usr_pay_type
FROM Payments p, Users u
WHERE status='PENDING'
AND p.usr_id=u.usr_id
ORDER BY u.usr_pay_type");
在数组结果中有一个名为“created”的字段。
我想要做的是将每行的另一个元素添加为“下一次付款”。
付款将在距日期时间值30天后处理,但仅在每个月的第6天处理。基本上我希望每个结果都有一个“下一个付款”元素,说明他们应该支付哪个日期和月份。
例如created = 2013-07-29 18:55:37 此后30天是2013年8月28日 因此,下一个付款日期将是9月6日
我不知道从哪里开始,任何人都可以提供的帮助将非常感谢!
由于
答案 0 :(得分:0)
以下显示逻辑:
select (date(t) - interval (day(t) - 1) day) + interval 1 month + interval 5 day
from (select cast(now() as datetime) as t) t;
您可以将其放入查询中:
SELECT p.*, u.usr_login, u.usr_money, u.usr_email, u.usr_pay_email, u.usr_pay_typel,
created - interval (day(created) - 1) day) + interval 1 month + interval 5 day as nextpay
FROM Payments p join
Users u
on p.usr_id=u.usr_id
WHERE status='PENDING'
ORDER BY u.usr_pay_type;
表达式可以简化为:
created - interval (day(created) + 4) day) + interval 1 month as nextpay
答案 1 :(得分:0)
如果我理解正确,您希望计算next_payment
日期,该日期是距离created
日期至少30天的最近的第6天。另一种说法是,您的截止日期始终是该月的第6天,且截止日期至少有30天的宽限期。
不幸的是,我们不能在这里进行简单的舍入或踩踏,因为公历不是一个常规的系列。 (这不是常规系列?)因此,我们将条件逻辑放入查询中。由于这看起来很糟糕,我们将其隐藏在一个函数中:
DELIMITER //
CREATE FUNCTION next_payment(close_date DATE)
RETURNS DATE
DETERMINISTIC
READS SQL DATA
LANGUAGE SQL
BEGIN
DECLARE min_grace INT DEFAULT 30; -- minimum grace period of 30 days
DECLARE bill_dom INT DEFAULT 6; -- billing day of month is the 6th
DECLARE d DATE;
SET d = close_date + INTERVAL min_grace DAY;
IF DAY(d) > bill_dom THEN -- Did 30 days\' grace put us beyond the 6th?
SET d = d + INTERVAL 1 MONTH; -- If so, advance to next month.
END IF;
RETURN d + INTERVAL(bill_dom - DAY(d)) DAY; -- Now "round" to the 6th of the month
END
//
DELIMITER ;
您如何使用逻辑取决于您。添加SELECT next_payment(p.created) AS "next_payment", ...
会为您提供所需的其他列。您可以参数化上述内容(例如CREATE FUNCTION next_payment(close_date DATE, min_grace INT, bill_dom INT)
)以获得更大的灵活性。您可能会将SET / IF逻辑从函数中删除并将其卡入SELECT中的一个难以处理的CASE / END语句中。您可以创建一个VIEW,自动将next_payment
列“追加”到表中,或者ALTER TABLE并填充新列等。