背景
您可以使用 Informix 函数 TODAY、MONTH()、YEAR() 和 MDY() 来做到这一点 — 以及一些小技巧。
本月第一天的表达式为:
MDY(MONTH(TODAY), 1, YEAR(TODAY))
因此,上个月第一天的表达式为:
MDY(MONTH(TODAY), 1, YEAR(TODAY)) - 1 UNITS MONTH
这些表达式的优点是它们明确且可靠;他们不依赖任何特殊的东西(在您编写的 SQL 中)来查找该月的最后一天。您可以通过从下个月的第一天减去 1 UNITS DAY 来找到该月的最后一天。使用现代版本的 Informix,您可以进行四舍五入到月底的日期算术:
SELECT MDY(1,31,2016) + 1 UNITS MONTH FROM sysmaster:'informix'.sysdual;
2016-02-29
但旧版本的 Informix 会产生错误。即使是现在,MDY(2,31,2016) 也会生成“月中日期无效”错误。
回答
所以对于题中的问题,你想要的日期范围是:
SELECT *
FROM taxes
WHERE effect_date >= (MDY(MONTH(TODAY), 1, YEAR(TODAY)) - 1 UNITS MONTH)
AND effect_date < MDY(MONTH(TODAY), 1, YEAR(TODAY))
使用“在本月的第一天之前”比使用“在上个月的最后一天或之前”更容易。但是你可以写:
SELECT *
FROM taxes
WHERE effect_date >= (MDY(MONTH(TODAY), 1, YEAR(TODAY)) - 1 UNITS MONTH)
AND effect_date <= (MDY(MONTH(TODAY), 1, YEAR(TODAY)) - 1 UNITS DAY)
或者,等效地:
SELECT *
FROM taxes
WHERE effect_date BETWEEN (MDY(MONTH(TODAY), 1, YEAR(TODAY)) - 1 UNITS MONTH)
AND (MDY(MONTH(TODAY), 1, YEAR(TODAY)) - 1 UNITS DAY)
使用存储过程
您可以通过使用任何选定的日期代替TODAY 来概括代码,如果您认为它们太晦涩,您可以编写一两个简单的存储过程来完成这些计算,如图所示。可能的名称包括first_day_this_month 和first_day_prev_month,将参考日期作为参数传递,默认为今天:
CREATE PROCEDURE first_day_this_month(refdate DATE DEFAULT TODAY)
RETURNING DATE AS first_day;
RETURN MDY(MONTH(refdate), 1, YEAR(refdate));
END PROCEDURE;
CREATE PROCEDURE first_day_prev_month(refdate DATE DEFAULT TODAY)
RETURNING DATE AS first_day;
RETURN MDY(MONTH(refdate), 1, YEAR(refdate)) - 1 UNITS MONTH;
END PROCEDURE;
使用示例(假设您的环境中有 DBDATE='Y4MD-' 或等效项,因此 DATE 字符串看起来像 ISO 8601 或 DATETIME 字符串):
SELECT first_day_this_month() AS aug_1,
first_day_prev_month() AS jul_1,
first_day_this_month(DATE('2015-12-25')) as dec_1,
first_day_prev_month(DATE('2015-10-31')) AS sep_1
FROM sysmaster:'informix'.sysdual;
输出:
aug_1 jul_1 dec_1 sep_1
2016-08-01 2016-07-01 2015-12-01 2015-09-01
因此:
SELECT *
FROM taxes
WHERE effect_date >= first_day_prev_month()
AND effect_date < first_day_this_month()