join 2 tables with SQL - sql

I have to join 2 tables with SQL in a special way:
TABLE1 has the fields GROUP and MEMBER, TABLE2 has the fields GROUP and MASTER.
I have to build a new TABLE3 with the fields GROUP and ID by copying TABLE1 to TABLE3 and search TABLE2 if there is a GROUP from TABLE1 and if, copy GROUP and MASTER to TABLE3.
Example:
table1:
group member
1 a
1 b
1 c
2 x
3 y
table2:
group master
3 n
3 z
1 k
9 v
2 m
7 o
8 p
Expected result, table3:
group id
1 a from table1
1 b from table1
1 c from table1
1 k from table2
2 x from table1
2 m from table2
3 y from table1
3 z from table2
3 n from table2
I hope everything's clear.
So what is the SQL query?
Thanks, Hein

The first part (copy members) should be easy:
INSERT INTO table3 (group, id) SELECT group, member FROM table1;
Then You just copy the masters, that are in groups, that are already present in table1:
INSERT INTO table3 (group, id) SELECT group, master FROM table2 WHERE group IN (SELECT DISTINCT group FROM table1);

Try this out. Of course you need to INSERT the whole selection to your new table named Table3.
WITH TABLE1(GRP,MMBR) AS
(SELECT 1, 'a' FROM DUAL UNION ALL
SELECT 1, 'b' FROM DUAL UNION ALL
SELECT 1, 'c' FROM DUAL UNION ALL
SELECT 2, 'x' FROM DUAL UNION ALL
SELECT 3, 'y' FROM DUAL),
TABLE2(GRP,MSTR) AS
(SELECT 3, 'n' FROM DUAL UNION ALL
SELECT 3, 'z' FROM DUAL UNION ALL
SELECT 1, 'k' FROM DUAL UNION ALL
SELECT 9, 'v' FROM DUAL UNION ALL
SELECT 2, 'm' FROM DUAL UNION ALL
SELECT 7, 'o' FROM DUAL UNION ALL
SELECT 8, 'p' FROM DUAL)
SELECT * FROM (
SELECT GRP, MMBR ID FROM TABLE1
UNION --UNION ALL if you need duplicates
SELECT GRP, MSTR ID FROM TABLE2
WHERE TABLE2.GRP IN (SELECT GRP FROM TABLE1)
)
ORDER BY GRP, ID

You can do it using UNION ALL and 2 simple SELECT in an INSERT as follows:
INSERT INTO table3(group,id)
SELECT group,id FROM table1
UNION ALL
SELECT group,id FROM table2
SELECT * FROM table3;
And if you don't want duplicate values,try this using UNION instead of UNION ALL:
INSERT INTO table3(group,id)
SELECT group,id FROM table1
UNION
SELECT group,id FROM table2
SELECT * FROM table3;

Related

SQL query to get both common and and non common data from 2 tables

Hi im looking for a query which will give me both common and non-common data in one query.
Table 2
ID
Assay
1
124
Result
required_missing
required_present
125
124
Based on req_ind column from table 1 , if req_ind is 1 and the same assay is present in table 2 i want to list it as above.
required missing column can have multiple column.
With the data given this gives requested result:
WITH table1 as (
select 1 as ID, 123 as Assay, 0 as req_ind from dual
union all
select 2,124,1 from dual
union all
select 3,125,1 from dual
),
table2 as (
select 1 as ID, 124 as Assay from dual
),
required_missing as (
select
row_number() over (order by table1.Assay) as R,
table1.Assay as required_missing
from table1
left join table2 on table2.Assay = table1.Assay
where table1.req_ind=1 and table2.id is null
),
requires_present as (
select
row_number() over (order by table1.Assay) as R,
table1.Assay as required_present
from table1
left join table2 on table2.Assay = table1.Assay
where table1.req_ind=1 and table2.id is not null
),
results as (
select row_number() over (order by (id)) as r
from table1
)
select rm.required_missing, rp.required_present
from results
left join required_missing rm on rm.R = results.R
left join requires_present rp on rp.R = results.R
where rm.R is not null or rp.R is not null;
output:
REQUIRED_MISSING
REQUIRED_PRESENT
125
124
If you want to have a comma separated list for missing and for present then you can use:
SELECT LISTAGG(CASE WHEN t2.assay IS NULL THEN t1.assay END, ',')
WITHIN GROUP (ORDER BY t1.assay) AS required_missing,
LISTAGG(t2.assay, ',')
WITHIN GROUP (ORDER BY t1.assay) AS required_present
FROM table1 t1
LEFT OUTER JOIN table2 t2
ON (t1.assay = t2.assay)
WHERE t1.req_ind = 1
Which, for the sample data:
CREATE TABLE table1 (id, assay, req_ind) AS
SELECT 1, 123, 0 FROM DUAL UNION ALL
SELECT 2, 124, 1 FROM DUAL UNION ALL
SELECT 3, 125, 1 FROM DUAL UNION ALL
SELECT 4, 126, 1 FROM DUAL UNION ALL
SELECT 5, 127, 1 FROM DUAL;
CREATE TABLE table2 (id, assay) AS
SELECT 1, 124 FROM DUAL UNION ALL
SELECT 2, 127 FROM DUAL;
Outputs:
REQUIRED_MISSING
REQUIRED_PRESENT
125,126
124,127
If you want the output in multiple rows then:
SELECT required_missing,
required_present
FROM (
SELECT NVL2(t2.assay, 'P', 'M') AS status,
ROW_NUMBER() OVER (
PARTITION BY NVL2(t2.assay, 'P', 'M')
ORDER BY t1.assay
) AS rn,
t1.assay
FROM table1 t1
LEFT OUTER JOIN table2 t2
ON (t1.assay = t2.assay)
WHERE t1.req_ind = 1
)
PIVOT (
MAX(assay)
FOR status IN (
'M' AS required_missing,
'P' AS required_present
)
)
Which outputs:
REQUIRED_MISSING
REQUIRED_PRESENT
125
124
126
127
db<>fiddle here

Getting a specific output from 2 tables

I have 2 tables :
tab_1 :
ID VAL
1 Y
2 N
3 Y
tab_2 :
ID VAL
2 N
3 X
4 Y
I want to get the final output like
ID Operation
1 INSERT
2 EQUAL
3 DIFF
4 DEL
I am in very basic level in joins so need some help in explanation/understanding this type of functionalities.Thanks in advance.
It appears that you want a full outer join between the two tables; and then a case expression to compare the val columns (both their existence and values) in both tables. Maybe something like:
-- CTEs for sample data
with tab_1 (ID, VAL) as (
select 1, 'Y' from dual
union all select 2, 'N' from dual
union all select 3, 'Y' from dual
),
tab_2 (ID, VAL) as (
select 2, 'N' from dual
union all select 3, 'X' from dual
union all select 4, 'Y' from dual
)
-- actual query
select coalesce(t1.id, t2.id) as id,
case
when t1.id is null then 'DEL'
when t2.id is null then 'INSERT'
when t2.val = t1.val then 'EQUAL'
else 'DIFF'
end as operation
from tab_1 t1
full outer join tab_2 t2 on t2.id = t1.id
order by id;
ID OPERATION
---------- ---------
1 INSERT
2 EQUAL
3 DIFF
4 DEL

Cannot figure out logic to update a table

I have below table.
TABLE: ABCD
B column have value 1 whenever there is a change in A column. Now I have to update the table like below. How can I do that?
You can do this using a correlated subquery:
update t
set b = (select sum(t2.b) from t t2 where t2.A <= t.A);
This is standard SQL and should work in either Oracle or Teradata.
Lets have a slightly more complicated example (where the changes in B are not correlated to the changes in A):
Oracle Setup:
CREATE TABLE ABCD( A, B ) AS
SELECT 1, 0 FROM DUAL UNION ALL
SELECT 1, 0 FROM DUAL UNION ALL
SELECT 1, 1 FROM DUAL UNION ALL
SELECT 2, 1 FROM DUAL UNION ALL
SELECT 2, 0 FROM DUAL UNION ALL
SELECT 3, 0 FROM DUAL UNION ALL
SELECT 3, 1 FROM DUAL UNION ALL
SELECT 3, 0 FROM DUAL;
Update:
UPDATE ABCD t1
SET b = (
SELECT sm
FROM (
SELECT ROWID AS id,
SUM( b ) OVER ( ORDER BY a, ROWNUM ) AS sm
FROM ABCD
) t2
WHERE t1.ROWID = t2.ID
);
Output:
SELECT * FROM ABCD;
A B
- -
1 0
1 0
1 1
2 2
2 2
3 2
3 3
3 3
(Note: This is an Oracle solution; I have no idea if it will or won't work in Teradata.)

How to find largest sequence of consecutive null values in a column

I want to get the maximum consecutive occurrence of null in a column as shown in the screenshot. As there is ID column also there in this table, ordering could be done based on it.
Like in this case, the output would be 4 as maximum 4 nulls are together.
SELECT * INTO #tmp FROM (Select 1 AS ID, 1 as lvl union all
Select 2, 1 union all
Select 3, Null union all
Select 4, Null union all
Select 5, 1 union all
Select 6, 1 union all
Select 7, Null union all
Select 8, Null union all
Select 9, Null union all
Select 10, Null union all
Select 11, 1 union all
Select 12, 1 union all
Select 13, 1 union all
Select 14, 1)x
SELECT * FROM #tmp
DROP TABLE #tmp
I just dont know from where to start, so any help would be appreciable.
Following the post at this link, I found the solution of my problem. The query giving correct result as 4 is:
SELECT TOP 1 COUNT(*)AS MaxNull
FROM
#tmp t
JOIN #tmp t2 ON t2.id <= t.id
WHERE NOT EXISTS(
SELECT 1
FROM #tmp t3
WHERE t3.id BETWEEN t2.id AND t.id
AND NOT t3.lvl IS NULL)
GROUP BY t.id
ORDER BY COUNT(*)DESC;

Exclude columns from Minus operations in oracle sql

I'd like to know if you can exclude a column from a MINUS operation
For example:
select column 1, column 2, column 3
from table 1
minus
select column 1, column 2
from table 2;
while column 3 is excluded from the operation.
Is there anyway to do that?
Thank you
You have a few alternatives.
#1
Minus without column3 then rejoin result to the original table to get the missing values for column3.
select *
from (
select column1, column2
from table1
minus
select column1, column2
from table2
)
join table1 using (column1, column2)
#2
Use an ANTI-JOIN the NOT EXISTS clause should work the same as NOT IN anyway.
select column1, column2, column3
from table1
where (column1, column2) not in (
select column1, column2
from table2
)
Perhaps you are after this?
select table1.column1, table1.column2, table1.column3
from table1
left table2 on table1.column1 = table2.column1 and table1.column2 = table2.column2
where table1.id IS NULL
This will result in only those table1 records that do not have matching column1 and column2 values in table2.
Look at this:
with t(a, b, c) as (
select 1, 2, 3 from dual union all
select 2, 2, null from dual union all
select 2, 3, 5 from dual
), t1(a, b) as (
select 1, 2 from dual union all
select 2, 2 from dual union all
select 2, 3 from dual
), t2 as (
select a, b, c from t
minus
select a, b, null from t1
)
select a, b from t2
A B
-----
1 2
2 3
SQLFiddle
If you have null values in your column3 and you want to escape them you can escape them like this:
with t(a, b, c) as (
select 1, 2, 3 from dual union all
select 2, 2, null from dual union all
select 2, 3, 5 from dual
), t1(a, b) as (
select 1, 2 from dual union all
select 2, 2 from dual union all
select 2, 3 from dual
), t3 as (
select a, b, nvl(c, -1) from t
minus
select a, b, null from t1
)
select a, b from t3
A B
-----
1 2
2 2
2 3
SQLFiddle