SQL 查询 Informix 以获取上个月的所有记录

SQL query for Informix to get all the records from previous month

我需要一个可以生成上个月生成的记录总数的查询。 我从这个查询开始:

select state, taxing_entity, count(taxing_entity) Total_TRXN_Count
from taxes where effect_date between '2016/07/01' and '2016/07/31' 
group by state, taxing_entity, effect_date

但我需要一个查询,它可以动态计算上个月的记录数,而无需对日期进行硬编码。我尝试了很多查询,例如:

SELECT * FROM taxes 
WHERE effect_date >= DATEADD(day,-30, getdate()) 
and effect_date <= getdate()

SELECT * 
FROM taxes
WHERE effect_date >= DATEADD(effect_date, -1, GETDATE()) 

但是直到现在我都没有成功。有人可以建议一种使用 SQL 的 Informix 方言获取上个月总记录的方法吗?

这应该适用于 MSSQL:

SELECT COUNT(*) 
FROM taxes
WHERE effect_date >= DATEADD(MONTH, -1, effect_date) 

我对 Informix 不太熟悉,但语法应该相差无几。

好吧,我已经准备好了,因为 sql-server 被标记了,你可以将它翻译成 informix,也许我也会查找它。

SELECT *
FROM
    taxes
WHERE
    effect_date >= DATEFROMPARTS(YEAR(DATEADD(MONTH,-1,GETDATE())),MONTH(DATEADD(MONTH,-1,GETDATE())),1)
    AND effect_date < DATEFROMPARTS(YEAR(GETDATE()),MONTH(GETDATE()),1)

我认为 infomix 可能只是:

SELECT *
FROM
    taxes
WHERE
    effect_date >= MDY(MONTH(ADD_MONTHS(CURRENT,-1)),1,YEAR(ADD_MONTHS(CURRENT,-1)))
    AND effect_date < MDY(MONTH(CURRENT),1,YEAR(CURRENT))

如果您从 <= 更改为 < 那么您实际上不必在上个月末搜索,而不必在本月初搜索。如果你 effect_date 包含时间,那实际上就是你想要的,因为午夜问题。

背景

您可以使用 Informix 函数 TODAYMONTH()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) 也会生成 'invalid day in month' 错误。

回答

所以对于题目中的问题,你想要的日期范围是:

SELECT *
  FROM taxes
 WHERE effect_date >= (MDY(MONTH(TODAY), 1, YEAR(TODAY)) - 1 UNITS MONTH)
   AND effect_date <   MDY(MONTH(TODAY), 1, YEAR(TODAY))

使用 'before the first day of this month' 比使用 'on or before the last day of the previous month' 更容易。但是你可以这样写:

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_monthfirst_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()

几岁了,但我认为这仍然是相关信息:

effect_date >=
    MDY(month(current - 1 units month), 1, year(current - 1 units month))
and effect_date < 
    MDY(month(current), 1, year(current))

http://www.dbforums.com/showthread.php?1627297-Informix-query-to-find-first-date-of-previous-month

当然,如果给你一个随机日期并且你需要涵盖从第一个到最后的月份,则模式类似:

effect_date >=
    MDY(month(<given_date>), 1, year(<given_date>))
and effect_date <
    MDY(month(<given_date> + 1 units month), 1, year(<given_date> + 1 units month))