PostgreSQL: How to define PARAMETER in query? [duplicate] - postgresql

This question already has answers here:
How to declare a variable in a PostgreSQL query
(15 answers)
Closed 7 years ago.
In MSSQL, I usually use below parameter like this:
declare #StartDate as date, #EndDate as date
set #StartDate = '08/01/2015' set #EndDate = '08/15/2015'
----------- and use it here as my Date Range of Records:
Select * from Table_Name
where DateRange between #StartDate and #EndDate
How can I do this in PostgreSQL for generating reports/records?

Reference to official documentation:
http://www.postgresql.org/docs/9.1/interactive/plpgsql-structure.html
http://www.postgresql.org/docs/9.1/static/plpgsql-declarations.html

Do like this
After $BODY$
DECLARE startdate date;
DECLARE enddate date;
After begin
startdate ='2015-08-01';
Enddate ='2015-08-15';
retrun query
select * from Table where daterange between startdate and endate

Related

How to create a function which will retrieve year, based on a certain logic

I need to create a function in DB2 which will retrieve year from the current date, based on a certain logic
If the number of the month of the current date is smaller and equal than 6 (=any month prior to June) then the previous year is the ‘reference year’
Else if the number of the month of the current date is larger than 6 (=any month after June!) then the current year is the ‘reference year’.
Examples:
The reference year for date ‘4/9/2019’ is 2018 , since 4 <= 6
The reference year for date ‘9/3/2019’ is 2019, since 9 > 6
Below is an example for the implementation for SQL Server:
CREATE FUNCTION dbo.getReferenceYear()
RETURNS int
AS
BEGIN
DECLARE #ret int;
SELECT #ret = MONTH(GETDATE())
IF (#ret <= 6)
SET #ret = (YEAR(GETDATE()) -1);
Else
SET #ret = (YEAR(GETDATE()) );
RETURN #ret;
END;
I need the same in db2.
Below is what I have tried
CREATE FUNCTION dbo.getReferenceYear()
RETURNS INT
BEGIN ATOMIC
DECLARE _month INT;
DECLARE _year INT;
SET _month = SELECT MONTH (current timestamp) FROM sysibm.sysdummy1
if(_month<=6)
SET _year = (SELECT YEAR (current timestamp) FROM sysibm.sysdummy1) -1
ELSE
SET _year = (SELECT YEAR (current timestamp) FROM sysibm.sysdummy1)
RETURN _year
END
Here is one way to do in in Db2-LUW:
CREATE or replace FUNCTION dbo.getReferenceYear()
RETURNS INT
BEGIN ATOMIC
declare v_nowts timestamp default current timestamp;
declare v_year int;
set v_year= year(v_nowts);
if ( month(v_nowts) <= 6 ) THEN
SET v_year = v_year -1;
END IF;
RETURN v_year ;
END
CREATE FUNCTION dbo.getReferenceYear()
RETURNS INT
as
BEGIN
DECLARE #month INT,#year INT;
SET #month = SELECT MONTH (ColumnName) FROM TableName
if(_month<=6)
SET #year = (SELECT YEAR (ColumnName) FROM TableName -1)
ELSE
SET #year = (SELECT YEAR (ColumnName) FROM TableName)
RETURN #year
END
Or if you don't have any column for the date and if you want to apply the same logic for the current date, then-
CREATE FUNCTION dbo.getReferenceYear()
RETURNS INT
as
BEGIN
DECLARE #month INT,#year INT;
SET #month =( SELECT MONTH (GETDATE()) )
if(#month<=6)
SET #year = (SELECT YEAR (GETDATE())-1)
ELSE
SET #year = (SELECT YEAR (GETDATE()) )
RETURN #year
END
I would do it like this
CREATE FUNCTION getReferenceYear()
RETURNS SMALLINT
RETURN YEAR(CURRENT DATE) - CASE WHEN MONTH(CURRENT DATE) <= 6 then 1 ELSE 0 END

How do I set EndDate by 3 months

I am struggling to accomplish set date if value is entered. So I wondering if someone could advise me how to do this. This is what I have done...
Declare
#StartDate DateTime,
#EndDate DateTime,
#Discount Varchar
If #Discount = 'Test123'
Begin
UPDATE tblName SET EndDate = case
When StartDate > dateadd(month,-3,getdate())
End
So what I am trying to do is if end-user enter Test123 the system will calculate that the EndDate would be (for example 11/08/2016) when the StartDate would be (for example 11/05/2016). Bearing mind before entering Testing123 the orginal EndDate has already been stored, for example 10/10/2016.
Thanks in advance for any help given.
Edit
I also continuing searching and found the following link
Here
If I understand your requirements correctly, I think you need something like this.
Declare
#StartDate DateTime,
#EndDate DateTime,
#Discount Varchar
If #Discount = 'Test123'
Begin
UPDATE tblName
SET EndDate = case
When StartDate > dateadd(month,-3,getdate())
Then dateadd(month,3,StartDate)
end
End

How to implement add_months in PostgreSQL? [duplicate]

This question already has answers here:
Calculating a date in Postgres by adding months?
(2 answers)
Closed 7 years ago.
How to implement add_months in PostgreSQL ??
Like oracle ADD_MONTHS returns the date.
Ex. ADD_MONTHS(hire_date,1)
use
hire_date + interval '1 month'
this will return exactly one month added to hire_date.
For More References on date and time functions in postgre Date time function
CREATE FUNCTION add_months(start DATE, months INT) RETURNS DATE AS
$$
SELECT (start + (months || ' months')::INTERVAL)::DATE
$$
LANGUAGE sql IMMUTABLE
In PostgreSQL you can create a function to do the job
create or replace function ADD_MONTHS(var_dte date,cnt int) returns setof date as
$$
declare
qry text;
begin
qry = format( 'select (''%s''::date + interval ''%s'')::date',var_dte,cnt||' month') ;
RETURN QUERY
EXECUTE qry;
end
$$
language plpgsql
and call this function
select ADD_MONTHS('2015-11-27',1)
Result:
add_months
date
----------
2015-12-27
in your case
select hire_date
,ADD_MONTHS(hire_date,1)
from table_name

Function Getting the right week number of year

I want to create a function to get the right week number of year.
I already posted here to find a 'native' solution, but apparently there is not.
I tryed to create funcrtion based on this mysql example
Here is the code translated to postgresql:
CREATE OR REPLACE FUNCTION week_num_year(_date date)
RETURNS integer AS
$BODY$declare
_year integer;
begin
select date_part('year',_date) into _year;
return ceil((to_char(_date,'DDD')::integer+(to_char(('01-01-'||_year)::date,'D')::integer%7-7))/7);
end;$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
But it gives wrong result, can someone help me ?
My config: PostgreSQL 9.2
If you want proper week numbers use:
select extract(week from '2012-01-01'::date);
This will produce the result 52, which is correct if you look on a calendar.
Now, if you actually want to define week numbers as "Every 7 days starting with the first day of the year" that's fine, though it doesn't match the week numbers anyone else uses and has some odd quirks:
select floor((extract(doy from '2011-01-01'::date)-1)/7)+1;
By the way, parsing date strings and hacking them up with string functions is almost always a really bad idea.
create or replace function week_num_year(_date date)
returns integer as
$body$
declare
_year date;
_week_number integer;
begin
select date_trunc('year', _date)::date into _year
;
with first_friday as (
select extract(doy from a::date) ff
from generate_series(_year, _year + 6, '1 day') s(a)
where extract(dow from a) = 5
)
select floor(
(extract(doy from _date) - (select ff from first_friday) - 1) / 7
) + 2 into _week_number
;
return _week_number
;
end;
$body$
language plpgsql immutable
You can retrieve the day of the week and also the week of the year by running:
select id,extract(DOW from test_date),extract(week from test_date), testdate,name from yourtable
What about the inbuild extract function?
SELECT extract (week from current_timestamp) FROM A_TABLE_FROM_YOUR_DB;

How to convert DATETIME to FILETIME value in T-SQL?

I need to convert a SQL Server DATETIME value to FILETIME in a T-SQL SELECT statement (on SQL Server 2000). Is there a built-in function to do this? If not, can someone help me figure out how to implement this conversion routine as a UDF (or just plain Transact-SQL)? Here is what I know:
FILETIME is 64-bit value representing the number of 100-nanosecond intervals since
January 1, 1601 (UTC) (per MSDN: FILETIME Structure).
SQL Server base time starts on 1900-01-01 00:00:00 (per SELECT CAST(0 as DATETIME)).
I found several examples showing how to convert FILETIME values to T-SQL DATETIME (I'm not 100% sure they are accurate, though), but could not find anything about reverse conversion. Even the general idea (or algorithm) would help.
Okay, I think I was able to implement this myself. Here is the function:
IF EXISTS
(
SELECT 1
FROM sysobjects
WHERE id = OBJECT_ID('[dbo].[fnDateTimeToFileTime]')
AND type = 'FN'
)
BEGIN
DROP FUNCTION [dbo].[fnDateTimeToFileTime]
END
GO
-- Create function.
CREATE FUNCTION [dbo].[fnDateTimeToFileTime]
(
#DateTime AS DATETIME
)
RETURNS
BIGINT
BEGIN
IF #DateTime IS NULL
RETURN NULL
DECLARE #MsecBetween1601And1970 BIGINT
DECLARE #MsecBetween1970AndDate BIGINT
SET #MsecBetween1601And1970 = 11644473600000
SET #MsecBetween1970AndDate =
DATEDIFF(ss, CAST('1970-01-01 00:00:00' as DATETIME), #DateTime) *
CAST(1000 AS BIGINT)
RETURN (#MsecBetween1601And1970 + #MsecBetween1970AndDate) * CAST(10000 AS BIGINT)
END
GO
IF ##ERROR = 0
GRANT EXECUTE ON [dbo].[fnDateTimeToFileTime] TO Public
GO
It seems to be accurate up to 1 second, which is okay with me (I could not make it more accurate due to data overflow). I used the TimeAndDate web tool to calculate the durations between dates.
What do you think?
2 SQL Server time era starts on
1900-01-01 00:00:00 (per SELECT CAST(0
as DATETIME).
No, that is the base date, datetime starts at 1753
run this
select cast('17800122' as datetime)
output
1780-01-22 00:00:00.000
But this is still less than filetime so you need to add that...however remember the gregorian and Julian calendars (also the reason that datetime starts at 1753)
The accepted answer work well, but will crash for date above 19 January 2038. Either use
DATEDIFF_BIG instead of DATEDIFF if you are on SQL Server 2016 or above, or use the following correction
CREATE FUNCTION [dbo].[fnDateTimeToFileTime]
(
#DateTime AS DATETIME
)
RETURNS
BIGINT
BEGIN
IF #DateTime IS NULL
RETURN NULL
DECLARE #MsecBetween1601And1970 BIGINT
DECLARE #MsecBetween1970AndDate BIGINT
DECLARE #MaxNumberDayBeforeOverflowDateDiff int;
SET #MaxNumberDayBeforeOverflowDateDiff = 24855; --SELECT DATEDIFF(day, CAST('1970-01-01 00:00:00' as DATETIME), CAST('2038-01-19 00:00:00' as DATETIME))
DECLARE #nbMaxDaysBetween1970AndDate int;
SET #nbMaxDaysBetween1970AndDate = DATEDIFF(day, CAST('1970-01-01 00:00:00' as DATETIME), #DateTime) / #MaxNumberDayBeforeOverflowDateDiff;
DECLARE #moduloResteDay int
SET #moduloResteDay = DATEDIFF(day, CAST('1970-01-01 00:00:00' as DATETIME), #DateTime) % #MaxNumberDayBeforeOverflowDateDiff;
DECLARE #nbSecondBefore19700101And20380119 bigint = 2147472000;
SET #MsecBetween1601And1970 = 11644473600000;
DECLARE #DateTimeModulo datetime;
SET #DateTimeModulo = DATEADD(day, -#nbMaxDaysBetween1970AndDate * #MaxNumberDayBeforeOverflowDateDiff, #DateTime)
SET #MsecBetween1970AndDate = CAST(CAST(#nbMaxDaysBetween1970AndDate as bigint) * #nbSecondBefore19700101And20380119 +
DATEDIFF(ss, CAST('1970-01-01 00:00:00' as DATETIME), #DateTimeModulo) as bigint)*
CAST(1000 AS BIGINT)
RETURN (#MsecBetween1601And1970 + #MsecBetween1970AndDate) * CAST(10000 AS BIGINT)
END