oracle subquery stored into a variable - sql

I have 2 tables table1 and table2.
create table table1
(
ID integer,
reg_number varchar(9),
primary_number varchar(9),
act varchar(1)
);
create table table2
(
SECONDARY_NUMBER varchar(9),
table1_id integer
);
I need to be able to grab all the rows from table1 that is associated with table2 so after an insert or update on column act from table1 to insert those rows into table3 table.
I have the query but I'm unsure how to store that query into a variable so I can call it into from a trigger.
The query
select * from table1 where id in (
with children as (
select id pid, primary_number pan from table1
where id = 20407 -- current id
and primary_number is not null -- child ids only
),
prime as (
select id pid from table1 p
inner join children c on c.pan = p.reg_number),
sibs as (
select secondary_number sec from table2 c
inner join prime on prime.pid = c.person_id ),
sibids as (
select id pid from table1 p
inner join sibs s on s.sec = p.reg_number)
select pid from children
union
select pid from prime
union
select pid from sibids
);
Thank you

Related

Query to pull the data from 3 tables based on latest load date and HashKey

I am trying write a SQL query to pull the data from 3 tables using JOINS on basis of common HashKey and I want to take all the updated records from 3rd table based on the load date(last increment/recent records) using SQL.
I have tried below SQL query but I am not able to get the recent record from third table.
SELECT
tab1.TennisID
tab1.TennisHashKey
tab3.LoadDate
tab2.TennisType
tab3.Clicks
tab3.Hit
tab3.Likes
fROM table1 tab1
LEFT JOIN table2 tab2
ON tab1.TennisHashKey = tab2.TennisHashKey
LEFT JOIN (SELECT * FROM Table3 WHERE LoadDate = (SELECT TOP 1 LoadDate FROM Table 3 ORDER BY LoadDate Desc)) tab3
ON tab2.TennisHashKey = tab3.TennishHashKey
I have matching number of records in Table 1 and Table 2, but there are multiple rows for same hashkey in Table3 based on loadDate.
Please provide your suggestion on this.
Thanks
Use ROW_NUMBER() to join only the most recent row from Table3.
SELECT
tab1.TennisID
, tab1.TennisHashKey
, tab3.LoadDate
, tab2.TennisType
, tab3.Clicks
, tab3.Hit
, tab3.Likes
FROM table1 tab1
LEFT JOIN table2 tab2
ON tab1.TennisHashKey = tab2.TennisHashKey
LEFT JOIN (
SELECT *
, ROW_NUMBER() OVER (PARTITION BY TennisHashKey ORDER BY LoadDate DESC) rn
FROM Table3
) tab3
ON tab2.TennisHashKey = tab3.TennishHashKey
AND rn = 1;
Another approach: you can use OUTER APPLY and get latest row and select it.
declare #table1 table(tennisid char(1), tennishashkey char(4),loaddate date)
declare #table2 table(tennishashkey char(4),tennistype char(10), loaddate date)
declare #table3 table(tennishashkey char(4),loaddate date,clicks int, hit int, likes int)
insert into #table1 values('A','A001','2020-01-01')
insert into #table2 values('A001','grass','2020-01-01')
insert into #table3 values('A001','2020-01-01',0,0,0),('A001','2020-01-01',1,1,1);
SELECT
tab1.TennisID
, tab1.TennisHashKey
, tab3.LoadDate
, tab2.TennisType
, tab3.Clicks
, tab3.Hit
, tab3.Likes
FROM #table1 tab1
LEFT JOIN #table2 tab2
ON tab1.TennisHashKey = tab2.TennisHashKey
OUTER APPLY (
SELECT TOP 1 *
FROM #Table3 as tab3
where tab3.tennishashkey = tab1.tennishashkey
order by loaddate desc
) tab3
TennisID
TennisHashKey
LoadDate
TennisType
Clicks
Hit
Likes
A
A001
2020-01-01
grass
1
1
1

Oracle while exists(select ...) insert into

I am trying to insert id's into a temporary table with while loop.
TEMP_TABLE contains ID-s which = ID of entry in ID_TABLE.
ID_TABLE has two fields CON_1 and CON_2, which refer to another entry in ID_TABLE.
I want to add all CON_1 and CON_2 values from ID_TABLE into TEMP_TABLE where ID_TABLE.ID = TEMP_TABLE.ID and CON_1 or CON_2 are not already in TEMP_TABLE and then repeat the process until there are no IDs left to insert (after adding CON_1 or CON_2 to TEMP_TABLE, those ID-s might refer to ID_TABLE.ID where CON_1 or CON_2 are not already present in TEMP_TABLE).
Basically, an ID might have connections as another ID and I want to add ID, it's connections and the connections for the connections ... into TEMP_TABLE.
The query I made this far:
begin
while exists(select extId
from (
select distinct case
when con.CON_1 = idTable.ID
then con.CON_2
else con.CON_1
end
as extId
from ID_TABLE idTable
inner join TEMP_TABLE temp on idTable.ID = temp.ID
inner join CONNECTIONS_TABLE con on con.CON_2 = idTable.ID
or con.CON_1 = idTable.ID)
where not exists(select ID from TEMP_TABLE where ID = extId))
loop
insert into TEMP_TABLE
select extId
from (
select distinct case
when con.CON_1 = idTable.ID
then con.CON_2
else con.CON_1
end
as extId
from ID_TABLE idTable
inner join TEMP_TABLE temp on idTable.id = temp.ID
inner join CONNECTIONS_TABLE con on con.CON_2 = idTable.id
or con.CON_1 = idTable.ID)
where not exists(select ID from TEMP_TABLE where ID = extId);
end loop;
end;
When I run the query, I get this error:
PLS-00103: Encountered the symbol "INNER" when expecting one of the following:
) , with group having intersect minus order start union where
connect
Running on Oracle 12c
You appear to be trying to recursively add CON_1 or CON_2 values from the CONNECTIONS_TABLE that were connected to a prior ID value in both the TEMP_TABLE and the ID_TABLE.
You don't appear to need the WHILE loop (or even PL/SQL) and can use a single MERGE statement and a hierarchical query:
MERGE INTO temp_table DST
USING (
SELECT DISTINCT
extid
FROM (
select con_1, con_2
from connections_table c
START WITH EXISTS(
SELECT 1
FROM ID_TABLE i
inner join TEMP_TABLE t
on ( i.id = t.ID )
WHERE i.id IN ( c.con_1, c.con_2 )
)
CONNECT BY NOCYCLE
PRIOR con_1 IN ( con_1, con_2 )
OR PRIOR con_2 IN ( con_1, con_2 )
)
UNPIVOT (
extid FOR con IN ( con_1 AS 1, con_2 AS 2 )
)
) src
ON ( src.extID = dst.id )
WHEN NOT MATCHED THEN
INSERT ( id ) VALUES ( src.extid );
Which for the initial setup:
CREATE TABLE temp_table( id ) AS
SELECT 1 FROM DUAL;
CREATE TABLE connections_table( con_1, con_2 ) AS
SELECT 1, 2 FROM DUAL UNION ALL
SELECT 3, 2 FROM DUAL UNION ALL
SELECT 3, 4 FROM DUAL UNION ALL
SELECT 5, 10 FROM DUAL;
CREATE TABLE id_table ( id ) AS
SELECT LEVEL FROM DUAL CONNECT BY LEVEL <= 10;
Would insert 3 rows and then:
SELECT * FROM temp_table;
Outputs:
ID
1
2
4
3
db<>fiddle here

Receiving duplicated results from UNION in SQL

I use SQL Server I use the following code:
CREATE TABLE table1
(
ID VARCHAR(10) NOT NULL PRIMARY KEY,
Name VARCHAR(3) NOT NULL,
Price INTEGER NOT NULL,
Date DATE
);
INSERT INTO table1 (ID, Name, Price, Date)
VALUES ('000212', 'Rod', 200, NULL);
CREATE TABLE table2
(
Descr VARCHAR(10) NOT NULL PRIMARY KEY,
Identity VARCHAR(10) NOT NULL,
amount INTEGER NOT NULL
);
INSERT INTO table2 (Descr, Identity, amount)
VALUES ('Silver rod', '000212', 3);
CREATE TABLE table3
(
Type VARCHAR(5) NOT NULL PRIMARY KEY,
Price INTEGER,
Condition INTEGER NOT NULL,
CatalogNum VARCHAR(10) NOT NULL
);
INSERT INTO table3 (Type, Price, Condition, CatalogNum)
VALUES ('Metal', NULL, 8, '000212');
INSERT INTO table3 (Type, Price, Condition, CatalogNum)
VALUES ('Wood', 300, 1, '000313');
WITH IdList AS
(
SELECT ID AS MasterId
FROM table1
UNION
SELECT Identity
FROM table2
UNION
SELECT CatalogNum
FROM table3
)
SELECT
i.MasterID,
t1.*,
t2.*,
t3.*
FROM
IdList as i
LEFT JOIN
table1 as t1 ON t1.ID = i.MasterID
LEFT JOIN
table2 as t2 ON t2.Identity = i.MasterID
LEFT JOIN
table3 as t3 ON t3.CatalogNum = i.MasterID;
SQL Fiddle demo
In order to combine several tables with the same product ID.
However for some reason I get multiple duplicated results. I.E. instead of getting one row with unique ID, I get 7 (I currently have 7 tables unlike the code above, but not necessarily - I also get 2, and 3 duplicated rows) with the same result.
Just to mention, this is a code which I found here and just edited and added 7 tables instead of only three that in the example above.

Insert into each column of a table values based on conditions

I have a table of products like this:
I want to delete duplicate rows in this table and use the Ids in other tables, so I used a temporary table to add just the Ids to delete and the Ids to keep:
-- create tmp table
create table #tmp (ProductId_ToKeep int, ProductId_ToDelete int);
-- collect the Products that have a lower id with the same name in the temp table
insert into #tmp (ProductId_ToKeep)
select [ProductId]
from dbo.[Product] t1
where exists
(
select 1
from dbo.[Product] t2
where t2.name = t1.name
and t2.[ProductId] > t1.[ProductId]
);
-- collect the Products that have a higher id with the same name in the temp table
insert into #tmp (ProductId_ToDelete)
select [ProductId]
from dbo.[Product] t1
where exists
(
select 1
from dbo.[Product] t2
where t2.name = t1.name
and t2.[ProductId] < t1.[ProductId]
);
select * from #tmp
After getting what I have in my temp table, I got this result:
I'm asking if any can one help me to put the Ids in each column as I want.
If I followed you correctly, you could use a window function to feed the transcodification table in a single query, like so:
insert into #tmp (ProductId_ToKeep, ProductId_ToDelete)
select *
from (
select
ProductId ProductId_ToDelete,
min(ProductId) over(partition by name) ProductId_ToKeep
from dbo.[Product]
) t
where ProductId_ToDelete != ProductId_ToKeep
The inner query pulls out the smallest ProductId for the given name; the outer query filters on record that should be deleted (ie whose ProductId is not the minimum ProductId for the same name).

select mutiple columns from 1 table insert into multiple rows of another table

how do I select multiple columns from table1 and insert into multiple rows of table2 if the values is not null
create table table2
(
label_id NUMBER(4),
level_name VARCHAR2(20)
);
create table table1
(
level_name VARCHAR2(20),
class_name1 VARCHAR2(20),
class_name2 VARCHAR2(20),
class_name3 VARCHARS2(20)
)
create table table2
(
level_id NUMBER(4),
class_name VARCHAR2(20)
)
data in table0
1, k1
2, k2
data in table1
k1, roomA5, roomA6, roomA7
k2, roomB1, roomB2
the result table2
1, roomA5
1, roomA6
1, roomA7
2, roomB1
2, roomB2
I probably need to add another column in table2 to make it right. perhaps table2 should be(level_id, room_id, class_name)
thank you so much for the any help
Try with:
insert into Table2 t2
(
Level_Id,
Class_Name
)select
t0.Level_Id,
t1.Class_Name1
from Table0 t0
inner join Table1 t1 on t1.level_name = t0.level_name
Do it with each class, just must replace Class_Name1 with Class_Name2.
Here is how to do it, easy if you union all 3 select statements for each classname column.
insert into table2
select a.level_id, b.classname1
from table0 a
join table1 b on a.level_name = b.level_name
where b.classname1 is not null
union all
select a.level_id, b.classname2
from table0 a
join table1 b on a.level_name = b.level_name
where b.classname2 is not null
union all
select a.level_id, b.classname3
from table0 a
join table1 b on a.level_name = b.level_name
where b.classname3 is not null
Have you looked at the unpivot command?
http://www.oracle.com/technetwork/articles/sql/11g-pivot-097235.html
Of course, this assumes you are using oracle 11g, which is an assumption at this point.
insert into table2
select *
from table1
unpivot
(
level_name
for class_name in ("class_name1","class_name2","class_name3")
)
order by "Puchase Frequency", state_code
I don't have a DB to test with, but this might help. It seems like a clean way to do it.