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

对着背影说爱祢 提交于 2020-01-03 03:28:06

问题


I need a query which can generate the total no of records generated in the previous month. I started with this query:

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

But I need a query which can dynamically calculate the no of records for a previous month without hard coding the dates. I tried many queries like:

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

and

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

but I have had no success until now. Can someone please suggest a way to get the total records from a previous month using the Informix dialect of SQL?


回答1:


Background

You can do it with Informix functions TODAY, MONTH(), YEAR() and MDY() — and a little jiggery-pokery.

The expression for the first day of this month is:

MDY(MONTH(TODAY), 1, YEAR(TODAY))

The expression for the first day of the prior month, therefore, is:

MDY(MONTH(TODAY), 1, YEAR(TODAY)) - 1 UNITS MONTH

The advantage of these expressions is that they are unambiguous and reliable; they don't depend on anything special (in the SQL you write) to find the last day of the month. You can find the last day of the month by subtracting 1 UNITS DAY from the first day of the following month. With modern versions of Informix, you can do date arithmetic that rounds to the end of month:

SELECT MDY(1,31,2016) + 1 UNITS MONTH FROM sysmaster:'informix'.sysdual;
2016-02-29

but older versions of Informix would generate an error instead. Even now, MDY(2,31,2016) generates an 'invalid day in month' error.

Answer

So for the problem in the question, the date range you want is:

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

It is easier to use 'before the first day of this month' than to use 'on or before the last day of the previous month'. However you could write:

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)

or, equivalently:

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)

Using stored procedures

You could generalize the code by using any chosen date in place of TODAY, and you could write one or two simple stored procedures to do those calculations if you think they're too obscure as shown. Possible names would include first_day_this_month and first_day_prev_month, passing the reference date as an argument, defaulting to TODAY:

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;

Example use (assuming you have DBDATE='Y4MD-' or equivalent in your environment, so DATE strings look like ISO 8601 or DATETIME strings):

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;

Output:

aug_1        jul_1        dec_1        sep_1
2016-08-01   2016-07-01   2015-12-01   2015-09-01

And hence:

SELECT *
  FROM taxes
 WHERE effect_date >= first_day_prev_month()
   AND effect_date <  first_day_this_month()



回答2:


A few years old but I assume this is still relevant info:

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

Of course if you were given a random date and you need to cover it's month from the first to the end, the pattern is similar:

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



回答3:


well I had this prepared because sql-server was tagged you can translate the it to informix maybe I will look it up too.

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)

I think infomix might just be:

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

If you change from <= to < then you really don't have to search by end of last month but rather than beginning of this month. Which if you effect_date has time included would actually be what you want because of the midnight issue.




回答4:


This should work in MSSQL:

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

I'm not too familiar with Informix, but the syntax shouldn't be too far off.



来源:https://stackoverflow.com/questions/39003297/sql-query-for-informix-to-get-all-the-records-from-previous-month

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!