How to select specific dates in PostgreSQL? - postgresql

My table:
create table example
(
code varchar(7),
date date,
CONSTRAINT pk_date PRIMARY KEY (code)
);
Dates:
insert into example(code, date)
values('001','2016/05/12');
insert into example(code, date)
values('002','2016/04/11');
insert into example(code, date)
values('003','2017/02/03');
My problem: how to select the previous dates to six month from today ?
In MySQL I can use PERIOD_DIFF,but, in PostgreSQL?

You can try INTERVAL instruction :
SELECT date
FROM example
WHERE date < CURRENT_DATE + INTERVAL '6 months'
AND date > CURRENT_DATE;
You will get the dates from today to six months.

Related

Make date_trunc() start on Sunday instead of Monday

Select date_trunc('week',dateTime) Date_week, Max(Ranking) Runing_Total_ID
from (select datetime, id , dense_rank () over (order by datetime) as Ranking
from Table1)
group by 1
This query is working for me to give me the running total of total IDs by week. But the week starts on Monday in Postgres by default. Is there any way to change the week start to SUNDAY?
Shift the timestamp back and forth:
Add a day before feeding the timestamp to date_trunc(), then subtract again:
SELECT date_trunc('week', datetime + interval '1 day') - interval '1 day' AS date_week
, max(ranking) AS runing_total_id
FROM (
SELECT datetime, dense_rank() OVER (ORDER BY datetime) AS ranking
FROM table1
) sub
GROUP BY 1;
See:
PostgreSQL custom week number - first week containing Feb 1st

DATE ADD function in PostgreSQL

I currently have the following code in Microsoft SQL Server to get users that viewed on two days in a row.
WITH uservideoviewvideo (date, user_id) AS (
SELECT DISTINCT date, user_id
FROM clickstream_videos
WHERE event_name ='video_play'
and user_id IS NOT NULL
)
SELECT currentday.date AS date,
COUNT(currentday.user_id) AS users_view_videos,
COUNT(nextday.user_id) AS users_view_next_day
FROM userviewvideo currentday
LEFT JOIN userviewvideo nextday
ON currentday.user_id = nextday.user_id AND DATEADD(DAY, 1,
currentday.date) = nextday.date
GROUP BY currentday.date
I am trying to get the DATEADD function to work in PostgreSQL but I've been unable to figure out how to get this to work. Any suggestions?
I don't think PostgreSQL really has a DATEADD function. Instead, just do:
+ INTERVAL '1 day'
SQL Server:
Add 1 day to the current date November 21, 2012
SELECT DATEADD(day, 1, GETDATE()); # 2012-11-22 17:22:01.423
PostgreSQL:
Add 1 day to the current date November 21, 2012
SELECT CURRENT_DATE + INTERVAL '1 day'; # 2012-11-22 17:22:01
SELECT CURRENT_DATE + 1; # 2012-11-22 17:22:01
http://www.sqlines.com/postgresql/how-to/dateadd
EDIT:
It might be useful if you're using a dynamic length of time to create a string and then cast it as an interval like:
+ (col_days || ' days')::interval
You can use date + 1 to do the equivalent of dateadd(), but I do not think that your query does what you want to do.
You should use window functions, instead:
with plays as (
select distinct date, user_id
from clickstream_videos
where event_name = 'video_play'
and user_id is not null
), nextdaywatch as (
select date, user_id,
case
when lead(date) over (partition by user_id
order by date) = date + 1 then 1
else 0
end as user_view_next_day
from plays
)
select date,
count(*) as users_view_videos,
sum(user_view_next_day) as users_view_next_day
from nextdaywatch
group by date
order by date;

Generate dates for postgres

i have a table
and i have a range from '2019-01-02' to '2019-01-04'
I need to generate ID and DATES (generated) from my table which started_at and ended_at (nullable) between the given range
result must be like this:
ID 4 from table is not included in result because it's started_at and ended_at not in range '2019-01-02' and '2019-01-04'
I need query that will do that in postgres.
Use generate_series()
select t.id, g.dt::date
from the_table t
cross join generate_series(t.started_at::date + 1,
least(t.ended_at::date, date '2019-01-04'),
interval '1 day') as g(dt)
where t.started_at >= date '2019-01-02'
and t.started_at < date '2019-01-04';
Worked this variant:
select t.id, g.dt::date from the_table t
cross join generate_series(t.started_at::date + 1,
least(t.ended_at::date, date '2019-01-04'), interval '1 day') as g(dt)
where dt >= date '2019-01-02' and dt < date '2019-01-04';

How to identify invalid dates in postgres table field?

I have a table in PostgreSQL that has two date fields ( start and end ). There are many invalid dates both date fields like 0988-08-11,4987-09-11 etc.. Is there a simple query to identify them? The data type of the field is DATE. Thanks in advance.
Values in a date column ARE valid per definition. The year 0988 = 988 is a valid historic date as well as the year 4987 which is far in the future.
To filter out dates which are too historic or too far in the future you simply make this query:
SELECT
date_col
FROM
table
WHERE
date_col < /* <MINIMUM DATE> */
OR date_col > /* <MAXIMUM DATE> */
For date ranges (your minimum and maximum date) you could use the daterange functionality:
https://www.postgresql.org/docs/current/static/rangetypes.html
https://www.postgresql.org/docs/current/static/functions-range.html
Example table:
start_date end_date
2015-01-01 2017-01-01 -- valid
200-01-01 900-01-01 -- completely too early
3000-01-01 4000-01-01 -- completely too late
0200-01-01 2000-01-01 -- begin too early
2000-01-01 4000-01-01 -- end too late
200-01-01 4000-01-01 -- begin too early, end too late
Query:
SELECT
start_date,
end_date
FROM
dates
WHERE
daterange('1900-01-01', '2100-01-01') #> daterange(start_date, end_date)
Result:
start_date end_date
2015-01-01 2017-01-01
demo:db<>fiddle
Those are valid dates, but if you have business rules that state they are not valid for your purpose, you can delete them based on those rules:
For example, if you don't want any dates prior to 1900 or after 2999, this statement would delete the records with those dates:
DELETE FROM mytable
WHERE
start_date < '1900-01-01'::DATE OR
start_date >= '2999-01-01'::DATE OR
end_date < '1900-01-01'::DATE OR
end_date >= '2999-01-01'::DATE;
If you want to replace the dates with the lowest/highest acceptable dates instead of deleting the entire record, you could do something like this:
UPDATE mytable
SET
start_date = least('2999-01-01'::DATE, greatest('1900-01-01'::DATE, start_date)),
end_date = least('2999-01-01'::DATE, greatest('1900-01-01'::DATE, end_date))
WHERE
start_date < '1900-01-01'::DATE OR
start_date >= '2999-01-01'::DATE OR
end_date < '1900-01-01'::DATE OR
end_date >= '2999-01-01'::DATE;

How do I convert a date ( YYYY-MM-DD ) into a month number in postgresql?

I got a table:
CREATE TABLE TRANSACTION (
transaction_date date,
id_transaction int,
PRIMARY KEY (id_transaction)
);
and I want to compare the month of 'transaction_date' field with a number of month.
SELECT *
FROM TRANSACTION T
WHERE month = transaction_date;
but I don't know how to make this conversion.
You can use EXTRACT(MONTH FROM transaction_date)
SELECT *
FROM transaction
WHERE EXTRACT(MONTH FROM transaction_date) = 1;
sqlfiddle demo
As per the documentation:
EXTRACT (field FROM source)
The extract function retrieves subfields such as year or hour from
date/time values. source must be a value expression of type timestamp,
time, or interval.
SELECT *
FROM TRANSACTION T
WHERE EXTRACT(MONTH FROM TIMESTAMP transaction_date) = month;
month should be an integer between 1 (January) and 12 (December).