In postgresql 10
select '2019-02-28'::timestamp + interval '1 months'
resulted to: 2019-03-28 00:00:00
It was supposed to return 2019-03-31 00:00:00
How to get actual result?
As far as I can see Postgres is giving the correct answers; adding one month to 2019-02-28 should result in 2019-03-28 in the same way that adding one month to 2019-02-27 should result in 2019-03-27. In these cases you are asking PostgreSQL to add one month to a specific date and it is doing this. Things do get interesting when you try something like select '2019-01-30'::timestamp + interval '1 months' (result 2019-02-28 00:00:00) but that's really the only logical choice (because 2019-02-30 is not valid).
I'm assuming that your real question is "given a timestamp, how do I get the last day in the following month"; if so try something like:
SELECT (date_trunc('MONTH', '2019-02-28'::timestamp) + INTERVAL '2 MONTH - 1 day');
Note: If you are using this in a query then you are probably better to get the first day of the following month so your query can say where xxx > month1 and xxx < followingmonth (otherwise you end up losing the last days data).
Related
I'm used to do the following syntax when analysing weekly data:
select week(creation_date)::date as week,
count(*) as n
from table_1
where creation_date > current_date - 30
group by 1
However, by doing this I will get just part of the first week.
Is there any smart way to alway get a whole week in the beginning?
Like get the first day of the week I would get half of.
First off you need to define what you mean by "week". This is more difficult than it appears. While humans have an intuitive since of a week, computers are just not that smart. There are 2 common conventions: the ISO-8601 Standard and, for lack of a better term, Traditional. ISO-8601 defines a week as always beginning on Monday and always containing 7 days. Traditional weeks begin on Sunday (usually) but may have weeks with less than 7 days. This results from having the 1st week of the year beginning on 1-Jan regardless of day of week. Thus the 1st and/or last weeks may have less than 7 days. ISO-8601 throws it own curve into the mix: the 1st week of the year begins on the week containing 4-Jan. Thus the last days of Dec may be in week 1 of the next year and the first days Jan may be in week 52/53 of the prior year.
All the below assume the ISO-8061.
Secondly there is no week function in Postgres. In you need extract function. So for this particular case:
select extract(week from creation_date)::integer as week, ...
Finally, your predicate (current_date - 30) ensures you will unusually not begin on the 1st of the week. To get the correct date take that result back 1 week, then go forward to the next Monday.
with days_to_monday (day_adj) as
( values ('{7,6,5,4,3,2,1}'::int[]) )
select current_date - 30
, current_date - 30 - 7 + day_adj[extract (isodow from current_date - 30 )]
from table_1 cross join days_to_monday;
The CTE establishes an array which for a given day of the week contains the number of days need to the next Monday. That main query extracts the day of week of current date and uses that to index the array. The corresponding value is added to get the proper date.
Putting that together with your original query to arrive at:
with next_week (monday) as
( values (current_date - 30 - 7
+ ('{7,6,5,4,3,2,1}'::int[])[extract (isodow from current_date - 30 )])
)
select extract(week from creation_date) as week,
count(*) as n
from table_1
where creation_date >= (select monday from next_week)
group by 1
order by 1;
For full example see fiddle.
I want to set day or hour time interval between 2 columns to get lates actual records, if I dont set this I got outdated information when I filter by day.
TableA: create_date
TableB: last_access_date
SO I did this
SELECT *
FROM acc_zone_person
WHERE create_time::date = last_access_time::date
I get daily information no outdated information, but at midnight all information between 23:00 - 00:00
disgarded I want to put interval so that my evening information from 19:00 will be present till 06:00 data.
I used
SELECT *
FROM acc_zone_person
WHERE last_access_time::date >= now() - interval '12 hours'
this time when I switch to older dates, I dont get any data, only data within 12 hours
so I need to find a way do something like this
SELECT *
FROM acc_zone_person
WHERE create_date::date >= last_access_time - interval '12 hours'
It should take create_date as NOW and get 12 hours interval data of last_access_time
According to your own statement: "It should take create_date as NOW ... "
SELECT *
FROM acc_zone_person
WHERE now()::date >= last_access_time - interval '12 hours'
I am a little confused here. Why couldn't you just use the last query you posted? Does it not work? Do you just need to convert the last_update_time to a date?
I'm running into an issue with a DB2 query for a Crystal Report. What I need to do is to pull the previous full month's data for a column, even if the previous month is December of the previous year (as it would be in January, for example). For instance, I have this table named TABLE:
Name Date
John 11/01/2019
Dave 12/15/2019
Frank 01/02/2020
I would need something like
select DATE from TABLE where month(DATE) = month(x)
In this instance, x = the full previous month's data, which in this case, would be December 2019, so it should return"
Dave 12/15/2019"
What's the code to pull the previous full month's data, regardless of what the current month and year are? Of course it should be dynamic, so it will pull the previous full month's data regardless when the query is run.
Try this
select date from table
where date between last_day(current_date - 1 month) + 1 day - 1 month
and last_day(current_date - 1 month)
or if your version of db2 knows first_day
select date from table
where date between first_day(current_date - 1 month)
and last_day(current_date - 1 month)
I was actually able to pick apart the IBM documentation to use the DB2 version of DATEPART and DATEADD. Here's what I came up with:
WHERE (DATE_PART('MONTH', COLUMN_DATE) = DATE_PART('MONTH', CURRENT_DATE - 1 MONTH) AND
DATE_PART('YEAR', COLUMN_DATE) = DATE_PART('YEAR', CURRENT_DATE - 1 MONTH))
I hope this helps someone in the future.
You may use any date instead of current date to return the first and last days of month previous to this given date.
This works for any Db2 version.
SELECT
CURRENT DATE - DAY(CURRENT DATE) + 1 - 1 MONTH AS FIRST_DAY
, CURRENT DATE - DAY(CURRENT DATE) AS LAST_DAY
FROM SYSIBM.SYSDUMMY1;
I am trying to fetch data from the current week and not from the last 7 days. My query is:
select
order_datetime_tz::date AS date,
orders
FROM
order_fact f
where order_datetime_tz < current_date
and order_datetime_tz >= date_trunc('week',current_date) - interval '1 week'
However this returns me the last 7 days..
Any idea on that?
Thanks!!
The beginning of the current week is date_trunc('week',current_date), so you just want to query dates later later than that:
select
order_datetime_tz::date AS date,
orders
FROM
order_fact f
where order_datetime_tz >= date_trunc('week',current_date)
How can I get this week's monday's date in PostgreSQL?
For example, today is 01/16/15 (Friday). This week's monday date is 01/12/15.
You can use date_trunc() for this:
select date_trunc('week', current_date);
More details in the manual:
http://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
If "today" is Monday it will return today's date.
SELECT current_date + cast(abs(extract(dow FROM current_date) - 7) + 1 AS int);
works, although there might be more elegant ways of doing it.
The general idea is to get the current day of the week, dow, subtract 7, and take the abs, which will give you the number of days till the end of the week, and add 1, to get to Monday. This gives you next Monday.
EDIT: having completely misread the question, to get the prior Monday, is much simpler:
SELECT current_date - ((6 + cast(extract(dow FROM current_date) AS int)) % 7)
ie, subtract the current day of the week from today's date (the number of day's past Monday) and add one, to get back to Monday.
And for other mondays:
Next Monday:
date_trunc('week', now())+ INTERVAL '7days'
Last week's monday:
date_trunc('week', now())- INTERVAL '7days'
etc. :)
I usually use a calendar table. There are two main advantages.
Simple. Junior devs can query it correctly with little training.
Obvious. Correct queries are obviously correct.
Assuming that "this week's Monday" means the Monday before today, unless today is Monday then . . .
select max(cal_date) as previous_monday
from calendar
where day_of_week = 'Mon'
and cal_date <= current_date;