Add number of days in given date - sql

In PostgreSQL:
Let say:
SELECT DATE(NOW())+interval '1 day';
It will show date tomorrow.
Problem:
While I having a column duration in table tbl, following SQL does not work :
SELECT DATE(NOW())+interval duration || ' day' from tbl;
I just wondering how to make the '1 day' become a variable instead of a constant.

Do not try to make '1day' a variable, just multiply it by duration variable:
SELECT DATE(NOW()+duration * INTERVAL '1day') FROM tbl;

Related

Incrementing Date - SQL(Snowflake)

I want to Increment/Decrement the Year , Day , Month by pulling in the Current Date in Snowflake in a single query ?
For e.g.
Suppose Current System Date - 04082021 I want to make it 05092022. I have tried the dateadd function but I suppose it allows only one part i.e. either year or month or day to be incremented at once.
Is it Possible ? If Not, What are the other alternatives ?
If you want to useDATEADD function, here is the code:
SELECT DATEADD(YEAR,+1,DATEADD(MONTH,+1,DATEADD(DAY,+1,CURRENT_DATE())));
returns 2022-09-05 from 2021-08-04
If you want to keep your format, Please use following code
SELECT TO_CHAR(DATEADD(YEAR,+1,DATEADD(MONTH,+1,DATEADD(DAY,+1,CURRENT_DATE()))),'DDMMYYYY');
I would do the arithmetic in thee parts:
select current_date + interval '1 year' + interval '1 month' + interval '1 day'
You can also use:
select current_date + interval '1 year, 1 month, 1 day'

How to save temporary session variables in PostgreSQL

Say I have a simple SQL statement like this:
SELECT * from birthday WHERE date < now() + INTERVAL '1 day' AND date > now() - INTERVAL '1 day';
but the equations for the "From" and "To" variables would be something more sophisticated than that. And I will be reusing the results of these equations in multiple queries. So, can I store them temporarily as we do in any programming language? I imagine something like:
$from := now() - INTERVAL '1 day';
$to:= now() + INTERVAL '1 day';
SELECT * from birthday WHERE date < $from AND date > $to;
I tried using SELECT INTO as suggested in this question but that's not what I want because it creates a whole database table just to save the variable, which also causes an error when reusing it in a later session even when using the TEMP parameter. It says "relationship already exists"!
I also tried some dollar sign $ syntax and some colon+equal := syntax and none works
SQL is not any programming language. If you want to store the values so you can re-use them in one query, then you can use a CTE:
WITH params as (
SELECT now() - INTERVAL '1 day' as _from,
now() + INTERVAL '1 day' as _to
)
SELECT *
FROM params CROSS JOIN
birthday b
WHERE date < params._to AND date > params._from;
If you want to repeat this across multiple queries, then I would recommend a temporary table:
CREATE TEMPORARY TABLE params AS
SELECT now() - INTERVAL '1 day' as _from,
now() + INTERVAL '1 day' as _to;
SELECT *
FROM params CROSS JOIN
birthday b
WHERE date < params._to AND date > params._from;
You can also encapsulate the code in a procedure/function. Or use some sort of scripting language or language such as Python.

how to replace date in postgres with a static number

I am writing a Postgres procedure and I want to replace only date part of date with some static no.
eg:-
varDate Date default '2018-05-21';
Say I want to make this date as '2018-05-08';
Can anyone tell how to achieve this.
Till now what i have tried is this
varDate := varDate - interval '1 day' * 21 + interval '1 day' * 8;
The above expression gives me proper results. But is there any shortcut to change only the date part of the date.
As far as I understand you want to change the day of the month to 8.
One way to do this is to "truncate" the date to the start of the month, then add 8 days:
vardate := date_trunc('month', vardate)::date + 8;
date_trunc returns a timestamp that's why the cast ::date is needed.
Another option is to "build" a date based on the existing date:
vardate := make_date(extract(year from vardate)::int, extract(month from vardate)::int, 8);
Another option is to add a number of days to the date so you land on the 8th day:
select vardate::date + (8 - extract(day from vardate) * interval '1 day'

Dynamic Date Table

I am creating a Data Model in PowerPivot and am wondering if there is anyway I can create a dynamic date table in SQL. I was able to create one in PowerQuery however there are some bugs in PowerQuery(read only connection) when a table is modified in PowerPivot. What I am looking for is to have a start date of 1/1/2013 (interval is days) and as each new year rolls around rows are added to the date table. Is there anyway to do this?
I am running Postgres
So far I came up with this,
SELECT * FROM dbo.fof_GetDates('1/1/2013', GETDATE())
But I want it to display all dates till end of the year.
The completely dynamic approach would be a query based on generate_series():
SELECT the_date::date
FROM generate_series('2013-01-01 0:0'::timestamp
, date_trunc('year', now()::timestamp)
+ interval '1 year - 1 day'
, interval '1 day') the_date;
Always use ISO 8601 format for dates and timestamps, which works irregardless of locale settings.
A final cast to date (the_date::date), because the function returns timestamp (when fed timestamp arguments).
The expression
date_trunc('year', now()::timestamp) + interval '1 year - 1 day'
calculates the last day of the current year. Alternatively you could use EXTRACT (year FROM now())::text || '-12-31')::date, but that's slower.
You can wrap this into a custom "table-function" (a.k.a. set-returning function) that you can basically use as drop-in replacement for a table name in queries:
CREATE OR REPLACE FUNCTION f_dates_since_2013()
RETURNS SETOF date AS
$func$
SELECT the_date::date
FROM generate_series('2013-01-01 0:0'::timestamp
, date_trunc('year', now()::timestamp)
+ interval '1 year - 1 day'
, interval '1 day') the_date;
$func$ LANGUAGE sql STABLE;
Example:
SELECT * FROM f_dates_since_2013();
Going one step further, you could create a table or - more elegantly - a MATERIALIZED VIEW based on this function (or the underlying query directly):
CREATE MATERIALIZED VIEW my_dates(the_date) AS
SELECT * FROM f_dates_since_2013();
Call:
SELECT * FROM my_dates;
All you have to do now is to schedule a yearly cron job that runs REFRESH MATERIALIZED VIEW at the start of each new year:
REFRESH MATERIALIZED VIEW my_dates;

PostgreSQL: SELECT integers as DATE or TIMESTAMP

I have a table where I have multiple integer columns: year, month and day. Unfortunately, while the three should have been grouped into one DATE column from the beginning, I am now stuck and now need to view it as such. Is there a function that can do something along the lines of:
SELECT makedate(year, month, day), othercolumn FROM tablename;
or
SELECT maketimestamp(year, month, day, 0, 0), othercolumn FROM tablename;
You can
SELECT format('%s-%s-%s', "year", "month", "day")::date
FROM ...
or use date maths:
SELECT DATE '0001-01-01'
+ ("year"-1) * INTERVAL '1' YEAR
+ ("month"-1) * INTERVAL '1' MONTH
+ ("day"-1) * INTERVAL '1' DAY
FROM ...
Frankly, it's surprising that PostgreSQL doesn't offer a date-constructor like you describe. It's something I should think about writing a patch for.
In fact, a quick look at the sources shows that there's an int date2j(int y, int m, int d) function at the C level already, in src/backend/utils/adt/datetime.c. It just needs to be exposed at the SQL level with a wrapper to convert to a Datum.
OK, now here's a simple makedate extension that adds a single function implemented in C, named makedate. A pure-SQL version is also provided if you don't want to compile and install an extension. I'll submit the C function for the 9.4 commitfest; meanwhile that extension can be installed to provide a fast and simple date constructor:
regress=# SELECT makedate(2012,01,01);
makedate
------------
2012-01-01
(1 row)
PostgreSQL 9.4+
In PostgreSQL 9.4, a function was added to do just this
make_date(year int, month int, day int)
There may be a more elegant method, but this will give you a date.
select to_date(to_char(year * 10000 + month * 100 + day,'00000000'), 'yyyymmdd')
from tablename;
Try something like:
SELECT year * interval '1 year' +
month * interval '1 month' +
day * interval '1 day'
FROM tablename;