Apply inner join on two tables constructed with minus - sql

I have two versions of the same table and want to find the differences between both: which rows have changed? I use a minus query twice to print the changed rows as they appear in the old and new table.
Now I want to add a new query: one that shows me the rows that have changed on a specific column.
(select * from NewTable minus select * from OldTable) NewRows
inner join
(select * from OldTable minus select * from NewTable) OldRows
on NewRows.column1 = OldRows.column1
and NewRows.column2 <> OldRows.column2
where column1 is the unique row id and column 2 is the changed property.
When I execute Oracle SQL Developer I get error ORA-00933 "SQL command not properly ended", and he indicates the definition of NewRows as error. I have also tried with ") as NewRows" but it did not work.
The following query does work, so the NewTable and OldTable are compatible.
(select * from NewTable minus select * from OldTable)
union
(select * from OldTable minus select * from NewTable)

Try with additional select * from on the beginning:
select * from
(select * from NewTable minus select * from OldTable) NewRows
inner join
(select * from OldTable minus select * from NewTable) OldRows
on (NewRows.column1 = OldRows.column1 and NewRows.column2 <> OldRows.column2)
Also be aware of nulls your condition for difference <> will not cover situation where one value is null and second is not null. You should probably use:
on (nvl(NewRows.column1, 'UNIQUEVAL1') = nvl(OldRows.column1, 'UNIQUEVAL1')
and nvl(NewRows.column2, 'UNIQUEVAL2') <> nvl(OldRows.column2, 'UNIQUEVAL2') )

Related

Why this subquery fails?

select *
from
(select * from person) as t1; /*ok*/
select *
from
(select * from person) as t1
where t1.birthday >= '1987-04-09'; /*ok*/
select *
from
(select * from person) as t1
where
t1.birthday = (select max(birthday) from t1); /* fails with 't1 doesn't exist' */
I know that the correct SQL for the 3rd query is
select *
from person
where person.birthday = (select max(birthday) from person) /*ok*/
Would anyone help me understand why the 3rd SQL query failed?
Thanks a lot
The SQL Query Execution Order is:
From/Join
Where
Group By
Having
Select
Distinct
Order by
In your case, 'from t1' will be executed first and it will throw an error because t1 hasn't yet been recognised by the DB.
Better use the table name instead of t1.

Updating the SQL query from Count(*) to EXISTS in SQL Server

I have the following SQL query,
CASE
WHEN (SELECT COUNT(*)
FROM MyTable AS Parameter
INNER JOIN Table ON Parameter.Attribute1 = Table.Attribute2
WHERE FD.DefID= Parameter.DefID AND Parameter.VTypeID = 1) = 0
THEN (
SELECT * from Table2)
ELSE
NULL
END AS Items
Basically, I would like to ensure that conditional execution is only if the query result count is 0.
How should I modify it to use EXISTS/NOT EXISTS keyword?
You can use exists to do that like so:
SELECT * from Table2
WHERE NOT EXISTS(
SELECT 1
FROM MyTable AS Parameter
INNER JOIN Table ON Parameter.Attribute1 = Table.Attribute2
WHERE FD.DefID= Parameter.DefID AND Parameter.VTypeID = 1)

Is there a way to SELECT * and do a CASE expression

So something like this:
SELECT *,
CASE
WHEN
....
I'm coding in Teradata
In Teradata if you are going to include more derived columns with your * then you must include the table or alias name with the *
So:
SELECT
myTable.*,
myOtherTable.*,
CASE WHEN... END
FROM myTable
INNER JOIN myOtherTable ON
mytable.id = myOtherTable.id;
If you have a thousand tables being joined together then just toss that mess into a subquery so you can SELECT * FROM and then add you case in the main query:
SELECT t1.*
CASE WHEN... END
FROM
(
SELECT *
FROM myTable
INNER JOIN myOtherTable ON
mytable.id = myOtherTable.id
) AS t1;

Is there a quick way to compare two equally formatted tables in SQL?

I would like to make an SQL query to compare two tables with identical columns, both names and types. Each table has a unique key. I want the query to return any rows that contain unequal values. I know could do something like this
select *
from table_1, table_2
where
table_1.key = table_2.key
and (
table_1.col1 != table_2.col1 OR
table_1.col2 != table_2.col2 OR
...
)
but this would be tedious since there are a large and potentially variable number of columns.
edit
If it helps, I'm using a tsql system.
Not sure what type of DB you are using but if you are using SQL Server 2005 or higher try this:
select 'table1' as tblName, * from
(select * from table1
except
select * from table2) x
union all
select 'table2' as tblName, * from
(select * from table2
except select *
from table1) x
How abt this..
select * from table1 where not exists (select * from table2)
union all
select * from table2 where not exists (select * from table1)
Verified with SQL Server:
(select * from table1 except select * from table2)
union
(select * from table2 except select * from table1);
Verified with Oracle:
(select * from table1 minus (select * from table2))
union
(select * from table2 minus (select * from table1))

PostgreSQL query for equality between two tables

I have two tables A & B and i would like to have a query that :
return TRUE ONLY if the two tables are the same (i mean every lines in A are present in B & vice versa, no matter the line order)
I have use the keyword EXCEPT but it doesnt work in many cases
Thanks for your help.
select * from tablea except all select * from tableb
returns all rows from tablea that do not exist in tableb.
doing it the other way around
select * from tableb except all select * from tablea
returns all rows in tableb that do not exist in tablea.
so, now we can:
select count(*) from ( select * from tablea except all select * from tableb ) x;
to get number of "bad" rows in tablea, and:
select count(*) from ( select * from tableb except all select * from tablea ) x;
to get count of "bad" rows in tableb.
tables are the same if both counts are 0. and since neither count can be less than zero, then we can test if sum of the counts is 0:
select 0 = ( select count(*) from ( select * from tablea except all select * from tableb ) x ) + ( select count(*) from ( select * from tableb except all select * from tablea ) x );