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

Posted

技术标签:

【中文标题】Informix 的 SQL 查询以获取上个月的所有记录【英文标题】:SQL query for Informix to get all the records from previous month 【发布时间】:2016-08-17 17:53:03 【问题描述】:

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

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

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

【问题讨论】:

您使用的是什么版本的 SQL Server? 我正在使用 Informix。 【参考方案1】:

背景

您可以使用 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) 也会生成“月中日期无效”错误。

回答

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

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

【讨论】:

【参考方案2】:

几年前,但我认为这仍然是相关信息:

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

【讨论】:

除了我会使用 TODAY 而不是 CURRENT,...与您几乎在同一时间提出的相同答案。 (我的答案上的创建日期具有误导性;我不小心提交了大约 2 行文本作为答案,所以我将其删除并在删除状态下对其进行了编辑。) @Jonathan Whew!我只是在点击提交后才看到你的,但我很确定它以前不存在。我不知道任何 Informix,所以你必须告诉我为什么这样更好。 CURRENT 是 CURRENT YEAR TO FRACTION(3) 的缩写,因此它生成的是 DATETIME 值而不是 DATE,然后将其转换为 DATE。内部表示完全不同; DATE 是整数类型,第 1 天为 1900-01-01,但 DATETIME 基于 DECIMAL 类型。它们很容易相互转换,但 CURRENT 所涉及的工作比 TODAY 略多。但我忽略了这一点,因为- 1 UNITS MONTH 表示法使用 DATETIME(和 INTERVAL)类型,所以在我使用的代码中也存在 DATE 和 DATETIME 之间的转换并返回到 DATE。 在 Informix 中,TODAY - 1 是昨天,这很有用,但不一定立即显而易见。所有系统在处理日期时都会变得相当冗长——看看其他答案吧。【参考方案3】:

我已经准备好了,因为 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))

如果您从

【讨论】:

【参考方案4】:

这应该可以在 MSSQL 中使用:

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

我对 Informix 不太熟悉,但语法应该不会太远。

【讨论】:

这在 mssq 或我知道的任何 rdbms 中无效! DATEADD() 不接受 2 个日期作为参数 以上示例使用了 3 个参数:effect_date、-1 和 GETDATE() 表示当前日期。 哇是的,它使用了 3 个参数,但它不是无效的!阅读文档。第一个参数是日期部分,例如日、月、年,第二个是间隔,第三个是要修改的日期。 effect_date 是 datetime 数据类型的列,它不是 datepart。这远非有效,应该删除这个答案! 我编辑了答案 - 现在它是有效的。我只是把它弄混了。 effect_date 是他想要比较的日期。 是的,它现在是一个有效的声明,但不适用于我所知道的任何情况,因为它永远是正确的,effect_date 永远是> = 1个月前。如果他想要上个月当天的所有内容,则 GETDATE() 将是合适的。但是看到现在是八月,他要求从七月开始的一切。

以上是关于Informix 的 SQL 查询以获取上个月的所有记录的主要内容,如果未能解决你的问题,请参考以下文章

SQL 查询以获取每个位置的“最新”值

SQL查询以获取特定年份的当前日期(考虑月份和日期)的数据

Informix 查询计划

informix SQL查询咨询

sql查询标题信息以及informix中的列中的数据

Informix SQL 查询:返回不同结果的两个相似查询