I have two tables:
CREATE TABLE Test_Persons_A (
PersonID int,
LastName varchar(255),
FirstName varchar(255)
);
INSERT INTO Test_Persons_A
(PersonID,LastName,FirstName)
values(11,'LN_A1','FN_A1');
INSERT INTO Test_Persons_A
(PersonID,LastName,FirstName)
values(12,'LN_A2','FN_A2');
CREATE TABLE Test_Persons_B (
PersonID int,
LastName varchar(255),
FirstName varchar(255)
);
INSERT INTO Test_Persons_B
(PersonID,LastName,FirstName)
values(21,'LN_B1','FN_B1');
INSERT INTO Test_Persons_B
(PersonID,LastName,FirstName)
values(22,'LN_B2','FN_B2');
commit;
I want to conditionally use aggregation function on only one of the tables with IF and UNION ALL within WITH clause (based on this post https://stackoverflow.com/a/51330601/2041023). but is there an easier way to do this, without having to add another SELECT wrapping around this one like the following?
---------- use IF and UNION ALL, aggregation function COUNT, but return two rows ----------
var TEST_TBL varchar2(20);
exec :TEST_TBL := 'test_persons_a';
with Test_count_id as (
select COUNT(PersonID) as CNT_PID
from Test_Persons_A
where UPPER(:TEST_TBL) = 'TEST_PERSONS_A'
union all
select COUNT(PersonID) as CNT_PID
from Test_Persons_B
where UPPER(:TEST_TBL) = 'TEST_PERSONS_B'
)
select * from Test_count_id
result:
CNT_PID
----------
2
0
The inconvenience is even more obvious here:
---------- use IF and UNION ALL, aggregation function MAX, but return two rows, one of which is empty ----------
var TEST_TBL varchar2(20);
exec :TEST_TBL := 'test_persons_a';
with Test_max_id as (
select MAX(PersonID) as Max_PID
from Test_Persons_A
where upper(:TEST_TBL) = 'TEST_PERSONS_A'
union all
select MAX(PersonID) as Max_PID
from Test_Persons_B
where UPPER(:TEST_TBL) = 'TEST_PERSONS_B'
)
select * from Test_max_id
result:
MAX_PID
----------
12
(-- empty row)
So, how I can do this in a clean way?
EDIT: removed the extra question to avoid confusion
FURTHER EDIT: if I add another SELECT to wrap the SELECT ... UNION ALL ... SELECT, it kind of works, but like I said, I am hoping to avoid this ugliness:
---------- use IF and UNION ALL, and a wrapper, aggregation function MAX, but return one row ----------
var TEST_TBL varchar2(20);
exec :TEST_TBL := 'test_persons_a';
with Test_max_id1 as (
select Max_PID from (
select MAX(PersonID) as Max_PID
from Test_Persons_A
where UPPER(:TEST_TBL) = 'TEST_PERSONS_A'
union all
select MAX(PersonID) as Max_PID
from Test_Persons_B
where UPPER(:TEST_TBL) = 'TEST_PERSONS_B'
) where Max_PID is NOT NULL
)
select * from Test_max_id1
result:
MAX_PID
----------
12