Passing Multiple Values into an API/Getting Multiple Values - sql

Here's the issue that I'm working through today. We have an ERP system in place and I need to set up an event to email Purchase Order Authorizers (POA) whenever they have a Purchase Order ready for approval. This is pretty easy to set up for purchase orders where we have a single authorizer. However, some purchase orders need to be reviewed by a group of authorizers, specifically our QA group, before they can get approved.
I can get a list of authorizers for our QA group using the following:
select authorize_id from purch_authorize_group_line where authorize_group_id = '30-QA-NUC';
This query returns 50 rows of data.
I can also get the USERID associated with an Authorize ID using the following:
SELECT purchase_authorizer_api.get_userid('30','104351') FROM DUAL;
What I can't figure out is how to pass all values from the first query into the second one. This query:
SELECT purchase_authorizer_api.get_userid('30',(select authorize_id from purch_authorize_group_line where authorize_group_id = '30-QA-NUC')) FROM DUAL;
returns the error "ORA-01427: single-row subquery returns more than one row."
So, what I'm wondering, is whether there's a way for me to pass all 50 values from the first query into the second query and get USERIDs for all 50 users. If those USERIDs then I can get a notification email out to the QA group when they have a PO ready to approve.

Maybe you're looking for this.
SELECT purchase_authorizer_api.get_userid('30', authorize_id)
FROM purch_authorize_group_line
WHERE authorize_group_id = '30-QA-NUC';

This should help -
DECLARE
V_VARIABLE VARCHAR2(1024);
BEGIN
FOR REC IN (SELECT AUTHORIZE_ID AS VAL FROM PURCH_AUTHORIZE_GROUP_LINE WHERE AUTHORIZE_GROUP_ID = '30-QA-NUC')
LOOP
SELECT PURCHASE_AUTHORIZER_API.GET_USERID('30',R.VAL) INTO V_VARIABLE FROM DUAL;
..
..
../* You code processing logic */
END LOOP;
END;
/

Related

Execute same query multiple times with different parameter postgressql

I don't know how to easily explain what i need to do but i'll try.
Lets say i have a user table with 5 users.
id name
1 Steve
2 Pat
3 Robin
4 Carl
5 Sarah
instead of just do a select * from users i need to do this different and more difficult.
I need to build a query that for each row in users table runs a query with a parameter (name) and then gives me the same output as select * from users
I know it's sounds wierd but this is what i actually needs to do..
So what i want to happen is this:
I need to loop thru the users table to find out how many rows there is. (5)
-That's the amount of times I want to execute the query.
For each execution of the Query i need to change name in the where clause. First execution = Steve, second = Pat and so on.
In the end I want just one output with everything together so I need to union the result.
If i would this manually it would look like this:
Select id, name from users where name = 'Steve'
union all
Select id, name from users where name = 'Pat'
union all
Select id, name from users where name = 'Robin'
union all
Select id, name from users where name = 'Carl'
union all
Select id, name from users where name = 'Sarah'
In my real case i need separate queries so a in ('Steve', 'Pat') or a solution like that won't work.
I hope you understand what im looking for, and if you have any question please ask. Im using postgres v.10
This should work as you intend to.
DO $$
DECLARE
var_req TEXT;
rec_key record;
cur_key CURSOR FOR SELECT distinct name from users;
BEGIN
open cur_key;
loop
fetch cur_key into rec_key;
EXIT WHEN NOT FOUND;
var_req := '
insert into your_output_table
select id, name from users
where name = '''||rec_key.name||'''
;
';
execute var_req;
end loop;
close cur_key;
END $$;

Function to calculate number of loans done in the previous year for SQL Server 2017

I have a Library loans table which records the LoanID, OutDate, DueDate, and InDate for each book loan. I want to create a function that will accept the previous year (ex. 2017) as input and output the number of loans for that year by counting the loan ids. I am able to do this but the number is repeated multiple times in the result set and I only want it to return one value.
create function Books.numLoansLastYear
(
#year as int
)
returns int
as
begin
declare #numLoans as int
select #numLoans = COUNT(LoanID)
from Reservations.Loan
where year(OutDate) = #year
return #numLoans
end
;
go
To test I am using the following query:
select Books.numLoansLastYear(year(GETDATE())-1) as 'Number of Loans'
from Reservations.Loan
;
The only way that I am able to resolve this is by using DISTINCT in my test query so I am wondering if my function is incorrect.
Any ideas?
I am a little unclear on your question. If your query were:
select l.*
from Reservations.Loan l;
You would not be surprised at getting multiple rows.
The same is true if you select anything with from and no filtering (or other conditions). You are selecting all the rows in the table. This is true even for a function call or constant.
I think you simply want:
select Books.numLoansLastYear(year(GETDATE())-1) as [Number of Loans];
Note the lack of from clause.

Oracle DB - count non-consecutive actions

Hi I have the scenario where the SQL in oracle db, should return the count of the shown variables value as below.
Action field will have Insert and Delete as a value for different time stamp but when I report the count it should be like for the given input.
The logic is all the Insert or all the Delete should be counted as 1 till it hits delete or Insert respectively.
Like a call center a customer can add any number of compliant (Insert) but that should be counted as 1 for that user id, if the already registered complaint is resolved (Delete) then next sequence of complaint (Insert) should be counted as one.
Any help is highly appreciated and Many thanks in advance!
Deva
Try this:
select keyfield, action, count(*) from (
select lead(action, 1, 'other') over (partition by keyfield order by timestamp) as naction, action from t1)
where action != naction group by action, keyfield;
Idea is to use analytic function to select only those records which are followed by other (ignore chains of same actions) action. Then group by action and id to do count.

SQL count, use only last record

can someone help me about counting rows in sql. I have a table, archive, in which I have bank account and status of that account. One account can have and usually have more records, in my count I have to use last record, not records before. Example:
account status
5552222 A
5552222 B
5552222 A
**5552222 B**
4445896 A
4445896 B
**4445896 A**
I have to use this who are bold. Based on this there is one B(blocked) and one A(active) account. I have column datetime, which can tell me what is last record. I just need query to count that
Assuming you want to count based on the most current row for an account:
SELECT tab.status,
COUNT(*)
FROM tab JOIN
(
SELECT account, MAX(datetime) AS maxdate
FROM tab
GROUP BY account
) AS dt
ON tab.account = dt.account
AND tab.datetime = dt.maxtime
GROUP BY tab.Status
SELECT COUNT(*)
FROM yourTable
WHERE Status='B'
or
WHERE AccountName LIKE '%B'
Edit: After OP modified the question to include the table data.
So, the problem is that the same account number can occur multiple times, and you want to count on the basis of last status of the account.
If the account is currently blocked, you would like to count it, irrespective of the number of times it gets blocked earlier.
Assumption: You have a date type column in your table which shows the date when the record's (with new status value) was inserted (or it may be an identity field which keeps track of the order of records created in the table)
The query will be:
SELECT COUNT (*)
FROM
(
SELECT DISTINCT
acNumber,
( SELECT Max(identityField_or_dateField)
FROM tableName t
WHERE t.acNumber = t2.acNumber AND Status='B')
FROM tableName t2
WHERE
( SELECT Max(identityField_or_dateField)
FROM tableName t
WHERE t.acNumber = t2.acNumber AND Status='B') IS NOT NULL
) tblAlias
Glad to help! Please remember to accept the answer if you found it helpful.

Getting original and modified content from a table with an audit trail

I came across the following table structure and I need to perform a certain type of query upon it.
id
first_name
last_name
address
email
audit_parent_id
audit_entry_type
audit_change_date
The last three fields are for the audit trail. There is a convention that says: all original entries have the value "0" for "audit_parent_id" and the value "master" for "audit_entry_type". All the modified entries have the value of their parent id for audit_parent_id" and the value "modified" for the "audit_entry_type".
Now what I want to do is to be able to get the original value and the modified value for a field and I want to make this with less queries possible.
Any ideas? Thank you.
Assuming a simple case, when you want to get the latest adress value change for the record with id 50, this query fits your needs.
select
p.id,
p.adress as original_address,
(select p1.adress from persons p1 where p1.audit_parent_id = p.id order by audit_change_date desc limit 1) as latest_address
from
persons p -- Assuming it's the table name
where
p.id = 50
But this assumes that, even if the address value doesn't change between one audit to the other, it remains the same in the field.
Here's another example, showing all persons that had an address change:
select
p.id,
p.adress as original_address,
(select p1.adress from persons p1 where p1.audit_parent_id = p.id order by audit_change_date desc limit 1) as latest_address
from
persons p -- Assuming it's the table name
where
p.audit_parent_id = 0
and
p.adress not like (select p1.adress from persons p1 where p1.audit_parent_id = p.id order by audit_change_date desc limit 1)
This can be solved with pure SQL in modern Postgres using WITH RECURSIVE.
For PostgreSQL 8.3, this plpgsql function does the job while it is also a decent solution for modern PostgreSQL. You want to ..
get the original value and the modified value for a field
The demo picks first_name as filed:
CREATE OR REPLACE FUNCTION f_get_org_val(integer
, OUT first_name_curr text
, OUT first_name_org text) AS
$func$
DECLARE
_parent_id int;
BEGIN
SELECT INTO first_name_curr, first_name_org, _parent_id
first_name, first_name, audit_parent_id
FROM tbl
WHERE id = $1;
WHILE _parent_id <> 0
LOOP
SELECT INTO first_name_org, _parent_id
first_name, audit_parent_id
FROM tbl
WHERE id = _parent_id;
END LOOP;
END
$func$ LANGUAGE plpgsql;
COMMENT ON FUNCTION f_get_org_val(int) IS 'Get current and original values for id.
$1 .. id';
Call:
SELECT * FROM f_get_org_val(123);
This assumes that all trees have a root node with parent_id = 0. No circular references, or you will end up with an endless loop. You might want to add a counter and exit the loop after x iterations.