PostgreSQL temp function for minimum date - sql

I am trying to create a temp function to avoid duplicating blocks of code in the script. I think by creating a temp function in PostgreSQL I will be able to keep the script succinct but I am unfamiliar with functions on PostgreSQL
I would like to get the minimum date value by a specific group,
i.e.
I have the following SQL script
select
my_tale.some_value_id
, min(my_tale.datetime::date)
filter(
where
my_tale.some_value_id_2 in (1, 2)
) as firs_date
from
my_tale
group by
1
I would like to swap out some_value_id_2 in a function so I don't have to reuse code, i.e. I don't want to do this:
select
my_tale.some_value_id
, min(my_tale.datetime::date)
filter(
where
my_tale.some_value_id_2 in (1, 2)
) as firs_date_1
, min(my_tale.datetime::date)
filter(
where
my_tale.some_value_id_2 in (3, 4)
) as firs_date_2
, min(my_tale.datetime::date)
filter(
where
my_tale.some_value_id_2 in (5, 6)
) as firs_date_3
from
my_tale
group by
1
Ideally I would like to have something like this:
select
my_tale.some_value_id
, temp_function(1,2) as firs_date_1
, temp_function(3,4) as firs_date_2
, temp_function(5,6) as firs_date_3
from
my_tale
group by
1
I have tried playing around with the function below, but can't get it to work:
create function pg_temp.get_first_date(id_1 int, id_2 int)
returns date
language sql
as $function$
min(my_tale.datetime::date)
filter(
where my_tale.some_value_id_2 in ($id_1, $id_2)
);
$function$
;
select
my_tale.some_value_id
, pg_temp.get_first_date(1,2) as firs_date_1
from
my_tale
group by
1
Any advice would be appreciated, thanks in advance

sql fiddle
reference: https://dba.stackexchange.com/questions/300507/what-does-begin-atomic-end-mean-in-a-postgresql-sql-function-procedure
begin;
create temp table mytable(mytableid bigint,some_value_id numeric, some_value_id_2 numeric, datetime date);
insert into mytable values (1,1,1,'2022-01-12');
insert into mytable values (1,1,2,'2022-03-01');
insert into mytable values (1,1,3,'2022-01-01');
insert into mytable values (1,1,1,'2022-01-11');
commit;
create function
pg_temp.get_first_date(id_1 int, id_2 int)
returns date
language sql
BEGIN ATOMIC
select min(datetime)
filter(where mytable.some_value_id_2 in ($1, $2)) from mytable;
end;

Related

Is it possible to insert multiple values using insert in sql

Is it possible to insert in one single query multiple values into a table ? .
I have declared this table
declare global temporary table CFVariables
(
CF varchar(255)
)
with replace ;
then i inserted values into the table
INSERT INTO qtemp.CFVariables ( CF ) VALUES
('F01' ), ('T01' ), ('U01' ), ('CIP' ), ('L01' )
Is it possible to not insert the values in qtemp.CFVariables table this way ? but like In ('F01' , 'T01' , 'U01' , 'CIP' , 'L01' )
Then , i declared my second table :
declare global temporary table xVariables
(
CFC numeric(3),
CF varchar(255)
)
with replace ;
In this part i'm having a problem to insert into my table xVariables
I tried to use this to insert multiple values
INSERT INTO qtemp.xVariables ( CFC, CF ) VALUES
( 1, (select CF from qtemp.CFVariables ))
My query field because i'm inserting more then one row to the table .
How can i achieve this ?
Try
INSERT INTO qtemp.xVariables ( CFC, CF ) SELECT 1 AS CFC,CF from qtemp.CFVariables;
Try running an insert-select:
INSERT INTO qtemp.xVariables ( CFC, CF )
select 1, CF from qtemp.CFVariables
To restrict the records to be inserted, you will need to do something like this:
INSERT INTO qtemp.xVariables ( CFC, CF )
select 1, CF
from qtemp.CFVariables
where CF in ('F01' , 'T01' , 'U01' , 'CIP' , 'L01' )

GetDate() returns constant literal error, how to solve? [duplicate]

Consider this table:
CREATE TABLE t (i int, j int, ...);
I want to insert data into a table from a set of SELECT statements. The simplified version of my query is:
INSERT INTO t VALUES ((SELECT 1), (SELECT 2), ...);
The real query can be much more complex, and the individual subqueries independent. Unfortunately, this standard SQL statement (which works on SQL Server) doesn't work on SQL Data Warehouse. The following error is raised:
Failed to execute query. Error: Insert values statement can contain only constant literal values or variable references.
Is there a way to work around this?
It appears that there are a few limitations on the INSERT .. VALUES statement of SQL Data Warehouse, but none on INSERT .. SELECT. The requested query can be rewritten to:
INSERT INTO t SELECT (SELECT 1), (SELECT 2);
This workaround is also useful when inserting multiple rows:
-- Doesn't work:
INSERT INTO t VALUES ((SELECT 1), 2), ((SELECT 2), 3), ...;
-- Works:
INSERT INTO t SELECT (SELECT 1), 2 UNION ALL SELECT (SELECT 2), 3;
You can also just run a CREATE TABLE AS SELECT (CTAS) statement. This gives you the full syntax support in the SELECT statement and control of the table shape (distribution type, index type) in the statement. A CTAS statement is fully parallalized.
Strange syntax, but it works. Here is a more complex example:
CREATE TABLE [MDM].[Fact_Management_Curve]
(
[Scenario_ID] INT NOT NULL,
[FundingYYYYMM] CHAR(6) NOT NULL,
[CollectionYYYYMM] CHAR(6) NOT NULL,
[CorpID] INT NOT NULL,
[Multipler] FLOAT NOT NULL
)
GO
INSERT INTO [MDM].[Fact_Management_Curve]
SELECT (SELECT 1), 201701, 201701, 21, 0.010170154301011 UNION ALL
SELECT (SELECT 1), 201701, 201702, 21, 0.010170278901234 UNION ALL
SELECT (SELECT 1), 201701, 201703, 21, 0.010170375659900 UNION ALL
SELECT (SELECT 1), 201701, 201704, 21, 0.010170482998344
GO
SELECT * FROM [MDM].[Fact_Management_Curve]
ORDER BY 1,2,3,4;
Scenario_ID FundingYYYYMM CollectionYYYYMM CorpID Multipler
1 201701 201701 21 0.010170154301011
1 201701 201702 21 0.010170278901234
1 201701 201703 21 0.0101703756599
1 201701 201704 21 0.010170482998344
For your information...
INSERT INTO table_name VALUES Syntax only accepts constant literal values or variable references. Anything like Expression is invalid.
For Example INSERT INTO table_name VALUES (A,B,A+B)
But
DECLARE #C INT = A+B
INSERT INTO table_name VALUES (A,B,C) is valid one.
Here A+B is like any kind of expressions so it throw the error like "only accepts constant literal values or variable references"

how to check Date is between 2 dates in SQL?

i want retrieve rows based on Date that within 2 dates or
it will be greater than date or less than date
where id =5
AND ( :fromDate is null or trunc ( :fromDate ) >= trun(TABLE.DEPOSIT_DATE ))
AND ( :toDate is null or trunc ( :toDate )<= trunc (TABLE.DEPOSIT_DATE ))
when i pass paramters to :fromDate and :ToDate at this format (7/25/2018 1:21:55 PM) for example
the query return 0 rows
Try using "BETWEEN" operator as below example
SELECT * FROM employee where joining_date BETWEEN '2006-02-14 04:34:33' AND '2016-02-15 04:34:12';
If you are using sql server
then first set the date format
like : - set daqteformat dmy
and date condition u can use between
like : Entrydate between '01/01/2018' and '31/01/2018'
Why you cannot use between ? check below example using plsql block statement to use bind variable the same as your example
SET serveroutput ON size 2000
/
declare
T_DATE date;
F_DATE DATE;
C_ID number(2);
begin
T_DATE := to_date('01/07/2018','dd/mm/yyyy');
F_DATE := to_date('01/06/2018','dd/mm/yyyy');
delete from ex_employee;
insert into ex_employee (id, X_NAME, T_ADDED) values (1, 'aa', sysdate);
insert into ex_employee
(id, X_NAME, T_ADDED)
values
(2, 'bb', sysdate - 1);
insert into ex_employee
(id, X_NAME, T_ADDED)
values
(3, 'cc', to_date('20/06/2018','dd/mm/yyyy'));
commit;
select id
into C_ID
from ex_employee
where T_ADDED between F_DATE and T_DATE or F_DATE is null or T_DATE is null;
dbms_output.put_line(c_id);
end;
/
PL/SQL procedure successfully completed
3

Insert values statement can contain only constant literal values or variable references in SQL Data Warehouse

Consider this table:
CREATE TABLE t (i int, j int, ...);
I want to insert data into a table from a set of SELECT statements. The simplified version of my query is:
INSERT INTO t VALUES ((SELECT 1), (SELECT 2), ...);
The real query can be much more complex, and the individual subqueries independent. Unfortunately, this standard SQL statement (which works on SQL Server) doesn't work on SQL Data Warehouse. The following error is raised:
Failed to execute query. Error: Insert values statement can contain only constant literal values or variable references.
Is there a way to work around this?
It appears that there are a few limitations on the INSERT .. VALUES statement of SQL Data Warehouse, but none on INSERT .. SELECT. The requested query can be rewritten to:
INSERT INTO t SELECT (SELECT 1), (SELECT 2);
This workaround is also useful when inserting multiple rows:
-- Doesn't work:
INSERT INTO t VALUES ((SELECT 1), 2), ((SELECT 2), 3), ...;
-- Works:
INSERT INTO t SELECT (SELECT 1), 2 UNION ALL SELECT (SELECT 2), 3;
You can also just run a CREATE TABLE AS SELECT (CTAS) statement. This gives you the full syntax support in the SELECT statement and control of the table shape (distribution type, index type) in the statement. A CTAS statement is fully parallalized.
Strange syntax, but it works. Here is a more complex example:
CREATE TABLE [MDM].[Fact_Management_Curve]
(
[Scenario_ID] INT NOT NULL,
[FundingYYYYMM] CHAR(6) NOT NULL,
[CollectionYYYYMM] CHAR(6) NOT NULL,
[CorpID] INT NOT NULL,
[Multipler] FLOAT NOT NULL
)
GO
INSERT INTO [MDM].[Fact_Management_Curve]
SELECT (SELECT 1), 201701, 201701, 21, 0.010170154301011 UNION ALL
SELECT (SELECT 1), 201701, 201702, 21, 0.010170278901234 UNION ALL
SELECT (SELECT 1), 201701, 201703, 21, 0.010170375659900 UNION ALL
SELECT (SELECT 1), 201701, 201704, 21, 0.010170482998344
GO
SELECT * FROM [MDM].[Fact_Management_Curve]
ORDER BY 1,2,3,4;
Scenario_ID FundingYYYYMM CollectionYYYYMM CorpID Multipler
1 201701 201701 21 0.010170154301011
1 201701 201702 21 0.010170278901234
1 201701 201703 21 0.0101703756599
1 201701 201704 21 0.010170482998344
For your information...
INSERT INTO table_name VALUES Syntax only accepts constant literal values or variable references. Anything like Expression is invalid.
For Example INSERT INTO table_name VALUES (A,B,A+B)
But
DECLARE #C INT = A+B
INSERT INTO table_name VALUES (A,B,C) is valid one.
Here A+B is like any kind of expressions so it throw the error like "only accepts constant literal values or variable references"

SQL query to know skipped number

Hi im new to SQL query i only know simple query.
My question is it possible to SELECT skipped check number EX2001,EX2002,EX2004
select result will show EX2003.
thanks in advance, sorry for my english.
you can answer algorithm only, ill try to implement it to SQL.
example:
SELECT * FROM SETTLEMENT WHERE checkno not in (between ex2001 and ex2900)
is it possible like this? im using MS SQL 2008.
create table sequence(st varchar(50))
insert into sequence values('EX2001');
insert into sequence values('EX2002');
insert into sequence values('EX2004');
insert into sequence values('EX2005');
insert into sequence values('EX2008');
Assuming your original table name is sequence with only one field, you can modify as per your needs
Try below
DECLARE #all TABLE
(
st varchar(20)
)
declare #start int
declare #end int
declare #str varchar(20)
set #start=2000 //define starting point
set #end=2010 //define end point
while(#start<#end)
BEGIN
SET #start=#start+1
set #str='EX'+cast(#start as varchar(20))
INSERT INTO #all VALUES (''+#str+'')
END
SELECT * from #all
except
select * from sequence
output
st
EX2003
EX2006
EX2007
EX2009
EX2010
if you need hard coded values in query then it can be done like (as you did not posted any code so here is a simple query). you can use IN() or NOT IN() in sql
select * from table where check_number not in ('EX2001','EX2002','EX2004' );
Since SQL engine is not mentioned, this answer is only for Oracle 11G
Option 1: With hierarchical queries
See Fiddle here
CREATE TABLE TEST1 ( A VARCHAR2 ( 9 ) );
INSERT INTO
TEST1
VALUES
( 'EX2001' );
INSERT INTO
TEST1
VALUES
( 'EX2002' );
INSERT INTO
TEST1
VALUES
( 'EX2004' );
COMMIT;
WITH TEST2
AS (SELECT
TO_NUMBER(SUBSTR ( A,
3 ))
AS A
FROM
TEST1)
SELECT
MIN_A
- 1
+ LEVEL
FROM
(SELECT
MIN ( A ) MIN_A,
MAX ( A ) MAX_A
FROM
TEST2)
CONNECT BY
LEVEL <= MAX_A
- MIN_A
+ 1
MINUS
SELECT A FROM TEST2;
Option 2: With Oracle analytics function
See Fiddle here
WITH T
AS (SELECT
TO_NUMBER(SUBSTR ( A,
3 ))
AS SNO,
SYSDATE AS SDATE
FROM
TEST1)
SELECT
SDATE,
SNO
+ 1
FIRST_MISSING,
DECODE ( NEXT_SNO
- 1,
SNO
+ 1, TO_NUMBER ( NULL ),
NEXT_SNO
- 1 )
LAST_MISSING
FROM
(SELECT
SDATE,
SNO,
LAG ( SNO )
OVER ( PARTITION BY SDATE
ORDER BY SNO )
LAST_SNO,
LEAD ( SNO )
OVER ( PARTITION BY SDATE
ORDER BY SNO )
NEXT_SNO
FROM
T)
WHERE
NVL ( NEXT_SNO,
SNO
+ 1 ) <> SNO
+ 1;