Generate days between dates in a generate series by month postgreSQL query - postgresql

I have a query the following query :
SELECT EXTRACT(YEAR FROM t::date),
EXTRACT(MONTH FROM t::date),t::date+ interval '1 month'- t::date
FROM generate_series('2015-04-01', '2016-02-09', '1 month'::interval) t
The query gives the correct number of days for all the months, except for the month of Feb, 2016 ie, I expect to get 9 days and not 29 days as the result. What change should I make to the query above? Thanks

Related

Postgres: How to change start day of week and apply it in date_part?

with partial as(
select
date_part('week', activated_at) as weekly,
count(*) as count
from vendors
where activated_at notnull
group by weekly
)
This is the query counts number of vendors activating per week. I need to change the start day of week from Monday to Saturday. Similar posts like how to change the first day of the week in PostgreSQL or Making Postgres date_trunc() use a Sunday based week but non explain how to embed it in date_part function. I would like to know how to use this function in my query and start day from Saturday.
Thanks in advance.
maybe a little bit overkill for that, you can use some ctes and window functions, so first generate your intervals, start with your first saturday, you want e.g. 2018-01-06 00:00 and the last day you want 2018-12-31, then select your data, join it , sum it and as benefit you also get weeks with zero activations:
with temp_days as (
SELECT a as a ,
a + '7 days'::interval as e
FROM generate_series('2018-01-06 00:00'::timestamp,
'2018-12-31 00:00', '7 day') as a
),
temp_data as (
select
1 as counter,
vendors.activated_at
from vendors
where activated_at notnull
),
temp_order as
(
select *
from temp_days
left join temp_data on temp_data.activated_at between (temp_days.a) and (temp_days.e)
)
select
distinct on (temp_order.a)
temp_order.a,
temp_order.e,
coalesce(sum(temp_order.counter) over (partition by temp_order.a),0) as result
from temp_order

How to query for a range of previous week (i.e. 14 days ago to 7 days ago)

I have the following query, but I'm trying to pull this data for the week before this. Is there a way to set a range between to points without referring to today or a set datestamp?
SELECT
Count(orders.id) AS order_count
FROM
orders
WHERE
orders.requested_delivery_date between CURRENT_DATE - INTERVAL '7 days' and now()
select count(orders.id) as order_count
from orders
where
date_trunc('week', requested_delivery_date) =
date_trunc('week', current_date - interval '7 days')

Getting a weird result for ISO Date in Postgresql

I have a table task_details. I need to select its weekly date from this table. I have used ISO Year & ISO Week to extract the weekly dates from this table as I want to extract its week number as 53 if its Dec,2015 then on the days 28 Dec,29 Dec,30 Dec,31 Dec and 1 Jan '16,2 Jan '16 since it should not separate to two different weeks for these sort of dates. The query I have used for ISO Year & ISO Week is given below.
select
name, id,
to_date(week || ' ' || yr, 'IW IYYY') week_date,
sum(worked_hours) worked_hours_per_week,
week, yr
from (
select
name, id,
newdate, hours worked_hours,
to_number(to_char(newdate, 'IW'), '99') week,
extract( year from newdate) yr
from task_details t
) sub
where worked_hours > 0
group by name, id, to_date(week || ' ' || yr, 'IW IYYY'), week, yr
order by yr, week
It is working fine for the weeks but then I am getting this weird result for one date for a record in the table. The table doesn't have the data for the year 2017.Also, the yr column is showing 2016 which is as desired but then the newdate column and week column is giving weird result. Why is this happening? How do I fix this ?
Here is the SQL fiddle for it :http://sqlfiddle.com/#!15/53abf/1
You should not mix week with year in the extract function as year is for the Gregorian calendar rather than the special ISO calendar.
See section 9.9.1 and comments about week.
to_number(to_char(newdate, 'IW'), '99') is effectively extract(week from newdate)
Changing the yr column to be extract(isoyear from newdate) solves your problem.
Adjusted SQL Fiddle
#gwaigh already cleared up your confusion of Gregorian and ISO year.
However, your query would be simpler and faster with date_trunc() to get the first day of each week:
SELECT name, id
, date_trunc('week', newdate)::date AS week_date
, extract(week FROM newdate)::int AS week
, extract(isoyear from newdate)::int AS isoyr -- must be ISO year to match
, sum(hours) AS worked_hours_per_week
FROM task_details
WHERE hours > 0
GROUP BY name, id, week_date, week, yr
ORDER BY week_date;
Also simplified your query.
SQL Fiddle.
Either way, if you work with timestamptz then year, week or date depend on your current timezone setting. (It can be a different year, depending on where you are right now.)

How to get current month and Last month in Redshift

I am wondering if I can get last month and current month in Redshift? I looked at functions at http://docs.aws.amazon.com/redshift/latest/dg/r_CURRENT_DATE_TIME_functions.html
For current month, I guess I can do the following:
LEFT(CURRENT_DATE, 7)
For previous month, I came up with the following:
LEFT(ADD_MONTHS(CURRENT_DATE, -1), 7)
But I am wondering if there is a simpler way of doing these?
SELECT EXTRACT(month FROM CURRENT_DATE);
SELECT EXTRACT(month FROM CURRENT_DATE - '1 month'::interval);

How to get the no of Days from the difference of two dates in PostgreSQL?

select extract(day from age('2013-04-06','2013-04-04'));`
gives me the no of days ! i.e.: 2 days
but it failed when I have a differnt month:
select extract(day from age('2013-05-02','2013-04-01'));
So what I need is to get the no of days as 32 days
Subtraction seems more intuitive.
select '2013-05-02'::date - '2013-04-01'::date
Run this query to see why the result is 31 instead of 32
with dates as (
select generate_series('2013-04-01'::date, '2013-05-02'::date, '1 day')::date as end_date,
'2013-04-01'::date as start_date
)
select end_date, start_date, end_date - start_date as difference
from dates
order by end_date
The difference between today and today is zero days. Whether that matters is application-dependent. You can just add 1 if you need to.