Generate difference between 2 tables listing columns from both tables - oracle

Have 2 tables with same columns and want to generate the difference between the tables and want to show the difference listing all columns from both tables
example:
select a.*,b.* from (
(
select a.col1,a.col2 from
(select col1, col2 from table1 minus select col1, col2 from table2) as a
)
union
(
select b.col1, b.col2 from
(select col1, col2 from table2 minus select col1, col2 from table2) as b
)
)
The result should be
a.col1 a.col2 b.col1 b.col2
a.FName a.ZipCode b.FName b.ZipCode
John <same value> Jane <same value as A>
Alpha 1234 Beta 2345
My query returns exception that it is missing R parenthesis after the 1st minus keyword

I think you are trying to find rows from table a which are missing in table b and rows in table b which are missing from table a. However, there is no point in joining these two sets. Try the following query and see if it works for you.
SELECT col1, col2, 'Missing from table 2' title
FROM
(
SELECT col1,
col2
FROM table1
MINUS
SELECT col1,
col2
FROM table2
)
UNION ALL
SELECT col1, col2, 'Missing from table 1' title
FROM
(
SELECT col1,
col2
FROM table2
MINUS
SELECT col1,
col2
FROM table1
)

Related

Fetch name based on comma-separated ids

I have two tables, customers and products.
products:
productid name
1 pro1
2 pro2
3 pro3
customers:
id name productid
1 cust1 1,2
2 cust2 1,3
3 cust3
i want following result in select statement,
id name productid
1 cust1 pro1,pro2
2 cust2 pro1,pro3
3 cust3
i have 300+ records in both tables, i am beginner to back end coding, any help?
Definitely a poor database design but the bad thing is that you have to live with that. Here is a solution which I created using recursive query. I don't see the use of product table though since your requirement has nothing to do with product table.
with
--Expanding each row seperated by comma
tab(col1,col2,col3) as (
Select distinct c.id,c.prdname,regexp_substr(c.productid,'[^,]',1,level)
from customers c
connect by regexp_substr(c.productid,'[^,]',1,level) is not null
order by 1),
--Appending `Pro` to each value
tab_final as ( Select col1,col2, case when col3 is not null
then 'pro'||col3
else col3
end col3
from tab )
--Displaying result as expected
SELECT
col1,
col2,
LISTAGG(col3,',') WITHIN GROUP( ORDER BY col1,col2 ) col3
FROM
tab_final
GROUP BY
col1,
col2
Demo:
--Preparing dataset
With
customers(id,prdname,productid) as ( Select 1, 'cust1', '1,2' from dual
UNION ALL
Select 2, 'cust2','1,3' from dual
UNION ALL
Select 3, 'cust3','' from dual),
--Expanding each row seperated by comma
tab(col1,col2,col3) as (
Select distinct c.id,c.prdname,regexp_substr(c.productid,'[^,]',1,level)
from customers c
connect by regexp_substr(c.productid,'[^,]',1,level) is not null
order by 1),
--Appending `Pro` to each value
tab_final as ( Select col1,col2, case when col3 is not null
then 'pro'||col3
else col3
end col3
from tab )
--Displaying result as expected
SELECT
col1,
col2,
LISTAGG(col3,',') WITHIN GROUP( ORDER BY col1,col2 ) col3
FROM
tab_final
GROUP BY
col1,
col2
PS: While using don't forget to put your actual table columns as in my example it may vary.

Error when inserting CTE table values into physical table

I have a complex query that creates a master CTE_Table form other CTE_Tables. I want to insert the results of the master CTE_Table into a physical table. I'm using Teradata version 15.10.04.03
SELECT Failed. [3707] Syntax error, expected something like a 'SELECT' keyword or '(' or a 'TRANSACTIONTIME' keyword or a 'VALIDTIME' keyword between ')' and the 'INSERT' keyword.
DROP TABLE dbname.physicalTablename ;
CREATE MULTISET TABLE dbname.physicalTablename ,
NO FALLBACK ,
NO BEFORE JOURNAL,
NO AFTER JOURNAL,
CHECKSUM = DEFAULT,
DEFAULT MERGEBLOCKRATIO
(
col1 INTEGER,
col2 INTEGER,
col3 INTEGER
)
NO PRIMARY INDEX ;
WITH
cteTable3 AS
( SELECT A.colA, A.colB, A.colC, B.col1, B.col2, B.col3
FROM cteTable1 A INNER JOIN cteTable2 ON (blah blah blah) ),
cteTable2 AS
( SELECT col1, col2, col3 FROM SourceTableB ),
cteTable1 AS
( SELECT colA, colB, colC FROM SourceTableA )
INSERT INTO dbname.physicalTablename
( col1, col2, col3, col4, col5, col6 )
SELECT
(C3.colA, C3.colB, C3.colC, C3.col1, C3.col2, C3.col3)
FROM cteTable3 C3 ;
While you are missing the INSERT portion of the question, I think the following might clear things up. The correct format for using a CTE in an INSERT is:
INSERT INTO <tablename>
WITH <cte> AS (SELECT...)
SELECT <fields> FROM <cte>
Consider the following:
CREATE MULTISET VOLATILE TABLE tmp AS (SELECT 'bobby' as firstname) WITH DATA ON COMMIT PRESERVE ROWS;
INSERT INTO tmp
WITH cte AS (select 'carol' as firstname)
SELECT * FROM cte;
SELECT * FROM tmp;
DROP TABLE tmp;

delete data from Table1 that doesn't exist in Table2

I have 2 different tables and I want to delete records from table1 which does not exist in Tables2
Table1:
select col1 from Table1
Table2:
select
concat('A_',col1)
from
Table2
where
Col2 = '748'
and Col3 = 'D'
and Col4 = 'Account'
now I want to delete the difference from Table1...
This can be done using the minus operation, and an insert into statement.
insert into table3(col) (
select col1 from Table1
minus
select
concat('A_',col1)
from
Table2
where
Col2 = '748'
and Col3 = 'D'
and Col4 = 'Account'
)
Records can then be deleted from table1 using a delete statement like
delete from table1
where col1 in (
select col1 from Table1
minus
select
concat('A_',col1)
from
Table2
where
Col2 = '748'
and Col3 = 'D'
and Col4 = 'Account'
)
delete from table1 t1
where not exists ( select * from table2 where col2 || col3 || col4 = t1.col1 );
This will work EXCEPT for the following situation; you need to explain what you want in that case. The DELETE statement can be modified to accommodate.
If t1.col1 is NULL, it will be deleted even if there are rows in table2 where col2, col3 and col4 are all NULL. Is that situation possible (where t1.col1 and col2, col3, col4 in table2 are all NULL? In that case, should the row in t1 be kept rather than deleted?

SQL query to get grouped sums and concatenated lists, preferably without using functions

I have a table like
colA colB colC
A 10 1
A 20 2
A 30 3
B 10 1
B 20 2
I want an output like this
ColA colB colC
A 60 1,2,3
B 30 1,2
Can someone tell me how to do it with and without using functions, and in PL/SQL?
Here is sql you needed.
Note : it will only run on oracle 11g R2 onwards.
with tab as(
select 'A' col1,10 col2,1 col3 from dual union all
select 'A' col1,20 col2,2 col3 from dual union all
select 'A' col1,30 col2,3 col3 from dual union all
select 'B' col1,10 col2,1 col3 from dual union all
select 'B' col1,20 col2,2 col3 from dual )
select col1, sum(col2),listagg(col3,',') WITHIN GROUP (ORDER BY col3) AS col3_list
from tab group by col1
Assume your table name is tab
with tab1(col1, col2) as (
select colA, sum(colB)
from tab group by colA
),
tab2(col1, col2) as (
select colA, LISTAGG(TO_CHAR(colC),',')
WITHIN GROUP (ORDER BY colC)
from tab group by colA
)
select a.col1, a.col2, b.col2
from tab1 a, tab2 b
where a.col1 = b.col1
OutPut:
COL1 COL2 COL2
A 60 1,2,3
B 30 1,2
For more information about LISTAGG link
This link explains about multiple with clause
Or simply;
select colA, sum(colB) colB,LISTAGG(TO_CHAR(colC),',')
WITHIN GROUP (ORDER BY colC)
from tab group by colA
Probably this may the easiest solution syntactically :)
SELECT COLA,
SUM(COLB),
WMSYS.WM_CONCAT(COLC)
FROM
(SELECT 'A' cola,10 AS colb,1 AS colc FROM dual
UNION
SELECT 'A' cola,20 AS colb,2 AS colc FROM dual
UNION
SELECT 'A' cola,30 AS colb,3 AS colc FROM dual
UNION
SELECT 'B' cola,10 AS colb,1 AS colc FROM dual
UNION
SELECT 'B' cola,20 AS colb,2 AS colc FROM dual
)
GROUP BY COLA ;
OUTPUT
COLA SUM(COLB) WMSYS.WM_CONCAT(COLC)
A 60 1,2,3
B 30 1,2

SQL Server 2012: Update table with inner join after sorted

I am using SQL Server 2012. I have a table called table1 like below:
Id col1 col2 col3 Name
1 a b abc null
2 b c mno null
And I have another table table2, like below:
Id col1 col2 col3 Name
1 % % abc Name1
2 a % abc Name2
3 % b abc Name3
4 a b abc Name4
I have to update Name column in Table1 From Name column in Table2 based on columns: col1, col2 and col3.
The Id = 1 in the table1 finds all 4 matches in the table because I am using like operator in col1 and col2 to compare(why I am using like is if it didn't find exact match it should accept % as a match).
Now my problem is if exact match is there for the columns col1, col2 and col3 in the table, it should consider that only not the rows with '%' value. For example, for the Id=1 in the table1, the result should be from id=4 in the table2.
I tried with following query:
UPDATE table1
SET name = t2.Name
FROM (SELECT TOP 1
t1.id, t2.name
FROM table1 t1
INNER JOIN table2 t2
ON t1.col3 = t2.col3 AND t1.col1 LIKE t2.col1
AND t1.col2 LIKE t2.col2
ORDER BY t2.col1, t2.col2) AS t3
WHERE id = t3.id;
But I am not getting result which I expected. And also, there are 8,000,000 records are there in table1 so it should not affect performance.
Please help to fix this issue.
At a first try, I suggest this:
UPDATE table1
SET name = t2.Name
FROM (SELECT TOP(1) *
FROM (SELECT
t1.id, t2.name, t2.col1, t2.col2, 2 As ord
FROM table1 t1
INNER JOIN table2 t2
ON t1.col3 = t2.col3 AND t1.col1 LIKE t2.col1
AND t1.col2 LIKE t2.col2
UNION ALL
SELECT
t1.id, t2.name, t2.col1, t2.col2, 1 As ord
FROM table1 t1
INNER JOIN table2 t2
ON t1.col3 = t2.col3 AND t1.col1 = t2.col1
AND t1.col2 = t2.col2
) DT
ORDER BY ord, col1, col2) AS t3
WHERE id = t3.id;

Resources