check if all table rows are equal - sql

There are two tables with identical structure.
Let's assume the number of rows in both is equal.
how would you check if all rows are equal? Is there any faster way than comparing every column value of a given row with the same id in both tables?

Try this:
SELECT * FROM table1
EXCEPT
SELECT * FROM table2
If anything is returned then they are not equal.

Abe's answer is correct, but only if they have the same number of rows. (I misread the question when I wrote my original response "condemning" his answer.) If table1 may be a subset of (a larger) table2 or vice versa, I would try:
if
(
not exists ( select * from table1
except
select * from table2
)
and
not exists ( select * from table2
except
select * from table1
)
)
This gives true if they are the same, and false if they are different.

Related

Get rows in sequence from multiple table in SQL Server

I want to get all rows in sequence from 2 tables in SQL Server.
Output should be 1st row from 1st table, then 1st row from 2nd table,
2nd row from 1st table, 2nd row from 2nd table....etc
What #eshirvana suggested will not get you the desired. Instead, it'll be table1.row1, table2.row1, table2.row2, table1.row2
You can use UNION to join data from two tables when the column names and types match. I'm making an assumption on how to order the data based on your desired outcome.
SELECT RowID, Row, z
FROM table1
UNION
SELECT *
FROM table2
ORDER BY z, RowID
Here's the working code:
https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=068c0fd2056cc48718345e85b74b7bba
probably something like that :
select * from
(
select rowID,Row,z from table1
union all
select rowID,Row,z from table2
) alltables
order by z
You can try with below approach:
SELECT * FROM
(
SELECT RowId,Row,Z,1 AS TableOrder From Table1
UNION ALL
SELECT RowId,Row,z,2 AS TableOrder From Table2
)
ORDER BY Z,TableOrder

Check if combination of fields in Table1 exists in another Table2 (SQL)

I need to check whether a combination of values in my table A exists in the specified corresponding set of columns in a different table, B.
So far, I'm doing this, which doesn't seem very elegant or efficient:
select * from table1 where
colX_table_1 NOT IN (select colX_table_2 from table2)
and
colY_table_1 NOT IN (select colY_table_2 from table2)
Is there a better/faster way to do this combination check (colX_table_1,colY_table_1) -> (colX_table_2,colY_table_2)?
The query you gave evaluates each field separately:
select * from table1 where
colX_table_1 NOT IN (select colX_table_2 from table2)
and
colY_table_1 NOT IN (select colY_table_2 from table2)
This is not merely unelegant, as you claim, it is wrong, as it does not enforce combinations. E.g., consider the following tables:
table1:
------
colX colY
1 1
table2:
------
colX colY
1 2
2 1
According to your post, you are looking for a query that would return the row in table1, since such a combination does not exist in table2. However, in the given query, each part of the where clause evaluates to false, and the row is not returned.
Instead, in order to check the combination and not each column individually, you could use an exists condition:
SELECT *
FROM table1
WHERE NOT EXISTS (SELECT *
FROM table2
WHERE table1.colx = table2.colx AND
table1.coly = table2.coly)
It depends a bit on your data but this worked in my case:
select *
from table1
where colx||coly not in (select colx||coly from table2)
This notation is just a string concatenation: ||

Postgresql UNION takes 10 times as long as running the individual queries

I am trying to get the diff between two nearly identical tables in postgresql. The current query I am running is:
SELECT * FROM tableA EXCEPT SELECT * FROM tableB;
and
SELECT * FROM tableB EXCEPT SELECT * FROM tableA;
Each of the above queries takes about 2 minutes to run (Its a large table)
I wanted to combine the two queries in hopes to save time, so I tried:
SELECT * FROM tableA EXCEPT SELECT * FROM tableB
UNION
SELECT * FROM tableB EXCEPT SELECT * FROM tableA;
And while it works, it takes 20 minutes to run!!! I would guess that it would at most take 4 minutes, the amount of time to run each query individually.
Is there some extra work UNION is doing that is making it take so long? Or is there any way I can speed this up (with or without the UNION)?
UPDATE: Running the query with UNION ALL takes 15 minutes, almost 4 times as long as running each one on its own, Am I correct in saying that UNION (all) is not going to speed this up at all?
With regards to your "extra work" question. Yes. Union not only combines the two queries but also goes through and removes duplicates. It's the same as using a distinct statement.
For this reason, especially combined with your except statements "union all" would likely be faster.
Read more here:
http://www.postgresql.org/files/documentation/books/aw_pgsql/node80.html
In addition to combining the results of the first and second query, UNION by default also removes duplicate records. (see http://www.postgresql.org/docs/8.1/static/sql-select.html). The extra work involved in checking for duplicate records between the two queries is probably responsible for the extra time. In this situation there should not be any duplicate records so the extra work looking for duplicates can be avoided by specifying UNION ALL.
SELECT * FROM tableA EXCEPT SELECT * FROM tableB
UNION ALL
SELECT * FROM tableB EXCEPT SELECT * FROM tableA;
I don't think your code returns resultset you intend it to. I rather think you want to do this:
SELECT *
FROM (
SELECT * FROM tableA
EXCEPT
SELECT * FROM tableB
) AS T1
UNION
SELECT *
FROM (
SELECT * FROM tableB
EXCEPT
SELECT * FROM tableA
) AS T2;
In other words, you want the set of mutually exclusive members. If so, you need to read up on relational operator precedence in SQL ;) And when you have, you may realise the above can be rationalised to:
SELECT * FROM tableA
UNION
SELECT * FROM tableB
EXCEPT
SELECT * FROM tableA
INTERSECT
SELECT * FROM tableB;
FWIW, using subqueries (derived tables T1 and T2) to explicitly show (what would otherwise be implicit) relational operator precedence, your original query is this:
SELECT *
FROM (
SELECT *
FROM (
SELECT *
FROM tableA
EXCEPT
SELECT *
FROM tableB
) AS T2
UNION
SELECT *
FROM tableB
) AS T1
EXCEPT
SELECT *
FROM tableA;
The above can be relationalised to:
SELECT *
FROM tableB
EXCEPT
SELECT *
FROM tableA;
...and I think not what is intended.
You could use tableA FULL OUTER JOIN tableB, which would give what you want (with a propre join condition) with only 1 table scan, it probably would be faster than the 2 queries above.
Post more info please.

SQL Server: Find Values that don't exist in a table

I have a list or set of values that I would like to know which ones do not currently exist in a table. I know I can find out which ones do exist with:
SELECT * FROM Table WHERE column1 IN (x,x,x,x,x)
The set is the values I am checking against. Is there a way to find out which values in that set do not exist in column1? Basically, I'm looking for the inverse of the sql statement above.
This is for a report, so all I need is the values that don't exist to be returned back.
I have and could do this with a left join and putting the values in another table, but the values I check are always different and was hoping to find a solution that didn't involve clearing a table and inserting data first. Trying to find a better solution for me if one exists.
You can also use EXCEPT as well as the OUTER JOIN e.g.
SELECT * FROM
(
SELECT -1 AS N
UNION
SELECT 2 AS N
) demo
EXCEPT
SELECT number
FROM spt_values
WITH q(x) AS
(
SELECT x1
UNION ALL
SELECT x2
UNION ALL
SELECT x3
)
SELECT x
FROM q
WHERE x NOT IN
(
SELECT column1
FROM [table]
)
Put the values you want to check for in a table A
LEFT OUTER JOIN the table A against your Table WHERE Table.column1 IS NULL
SELECT column1
FROM A
LEFT OUTER JOIN
Table
ON A.column1 = Table.column1
WHERE Table.column1 IS NULL
This will only show the rows that exist in A but not in Table.
As you want some of the values from the set in the result, and you can't take them from the table (as you want the ones that doesn't exist there), you have to put the set in some kind of table or result so that you can use that as source.
You can for example make a temporary result, that you can join against the table to filter out the ones that does exist in the table:
select set.x
from (
select 1 as x union all
select 2 union all
select 3 union all
select 4 union all
select 5
) as set
left join Table as t on t.column1 = set.x
where t.columnn1 is null
One way you can do it is:
SELECT * FROM Table WHERE column1 NOT IN(...);
Use the NOT operator:
SELECT * FROM Table WHERE column1 NOT IN (x,x,x,x,x)

Unselect the previous select

I don't know it may sound weird... but here is my situation... I have to select rows from two tables (Table1) and (Table2)
Select * from Table1 Where <SomeCondition>
Select * from Table2 Where <SomeCondition>
But my constraint is If Table1 / Table2 return 0(zero) Rows... I should not return any results at all.
That ie... If 1st select returns say 10 rows and the 2nd select returns 0 (zero) rows, I should call back the first select also...
Is the Temp tables the only solution, or do we have any other alternative.
Thanks in advance for your response...
Raja
One approach is to do an IF EXISTS first:
IF EXISTS(SELECT * FROM Table1 WHERE....) AND EXISTS(SELECT * FROM Table2 WHERE....)
BEGIN
-- Now do your SELECT on each, as both return results
END
EXISTS should give good performance, as it will stop as soon as it does find a matching record.
Without more details of your specific queries, here is an option. As long as your queries aren't too complex aren't very intensive, this should work:
Select * from Table1 Where <SomeCondition>
where exists( Select null from Table2 Where <SomeCondition> );
Select null from Table2 Where <SomeCondition>
where exists ( Select null from Table1 Where <SomeCondition> );
This will only select rows in each statement if the other statement will also return any number of rows greater than zero.
An obvious but not-so-performant solution will be to count number of rows first (not sure about the syntax):
if not exists(select id from Table1 where ...) or not exists(select id from Table1 where ...)
return
Select * from Table1 Where <SomeCondition>
Select * from Table2 Where <SomeCondition>
If you can use stored procedures you can use ##rowcount to check if the second query returned any results:
create proc pTest
as
Select * from Table1 Where <SomeCondition>
Select * from Table2 Where <SomeCondition>
if ##rowcount = 0 return
go