Comparing Two tables without knowing columns information - sql

If I have two tables A and B. I want to know if this table are same or not ?
i.e check does columns match ?
and does data match ?

SELECT *
FROM
(
(SELECT * FROM Table1
MINUS
SELECT * FROM Table2)
UNION ALL
(SELECT * FROM Table2
MINUS
SELECT * FROM Table1)
)

Query USER_TAB_COLUMNS for each table
SELECT table_name, column_name,
FROM USER_TAB_COLUMNS
WHERE table_name = 'MYTABLE'
And you can compare it for matching columns .
(hawk's answer will do it in one step.)

Related

Dynamic from clause

I have a table in which one column represent a name of a table in my db.
TableA
| tableName |
-------------
| table 1 |
| table 2 |
| ....... |
| table n |
What I need to do is to count all the records that are inside each table listed in tableA.
What I managed to do so far is this:
select count(*)
from (
select tableName
from tableA
) tables
but this is wrong because it counts the number of rows in the tableA table, which is not what I need.
The list of table don't have any relationship pretty much so there are no join operations, I just need to add to a counter the number of all records in each table.
Can that be done with a plain sql query? I'm using postgresql but would like to come up with a solution that doesn't depend on any db vendor.
select sum(row_count) as totalRecords
from(
select table_schema,
table_name,
(xpath('/row/cnt/text()', xml_count))[1]::text::int as row_count
from (
select table_name, table_schema,
query_to_xml(format('select count(*) as cnt from %I.%I', table_schema, table_name), false, true, '') as xml_count
from information_schema.tables t
join tableA ta on ta.tablename = t.table_name
)t
) t
A pure SQL solution that works in about any DBMS? Well, as you know you cannot simply query the table names from your control table and use these in a SQL FROM clause, because the table names in the control table are data while the table names in the FROM cause are structure, so to say.
As you should know your database, however, you can use the table names known to you and compare them to the entries in your control table:
select 'TABLE_1', count(*) from table_1 having 'TABLE_1' in (select tablename from tablea)
union all
select 'TABLE_2', count(*) from table_2 having 'TABLE_2' in (select tablename from tablea)
union all
select 'TABLE_3', count(*) from table_3 having 'TABLE_3' in (select tablename from tablea)
union all
select 'TABLE_4', count(*) from table_4 having 'TABLE_4' in (select tablename from tablea)
union all
select 'TABLE_5', count(*) from table_5 having 'TABLE_5' in (select tablename from tablea)
This query must be altered when new tables get added to the database. As adding tables to a database is something that happens seldom if ever, this shouldn't be an issue.
Demo: https://dbfiddle.uk/Dfk9nIFo

How can I compare the columns of 2 tables from 2 different datatables?

I need to compare the columns of two different tables from two different databases. Is there a way I can do this? I basically need to check if the columns within these two tables are the same or where they are different. I would like to list out the columns of these two tables side by side.
Table 1: abc.table1
Table 2: xyz.table2
I think you can do that simply by using 'INFORMATION_SCHEMA.COLUMNS' for SQL Server.
TO FIND SAME Columns IN (SQL SERVER)
SELECT T1.* FROM
(SELECT COLUMN_NAME
FROM [DatabaseName1].INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Table1'
) T1
INNER JOIN
(SELECT COLUMN_NAME
FROM [DatabaseName2].INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Table2'
) T2 ON T1.COLUMN_NAME=T2.COLUMN_NAME
To Find Uncommon Column
SELECT T1.* FROM
(SELECT COLUMN_NAME
FROM [DatabaseName1].INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Table1'
) T1
LEFT JOIN
(SELECT COLUMN_NAME
FROM [DatabaseName1].INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Table2'
) T2 ON T1.COLUMN_NAME=T2.COLUMN_NAME
WHERE T2.COLUMN_NAME IS NULL
Note: This will work for SQL Server only.

Column names from query

I'm trying to get make a query to return a list of the column names from a query result in postgresql
e.g.
SELECT column_name
FROM (
SELECT table1.*
FROM table1
LEFT JOIN table2
ON table1.id = table2.tbl1_id
)
is this possible
I DO NOT WANT THE COLUMNS FROM A SINGULAR TABLE!!! so please dont tell me to do
SELECT column_name
FROM information_schema.columns
WHERE table_name = 'table1'
I don't know why you would ever need to do this, but it is possible using some of the JSON functions introduced in 9.3.
SELECT json_object_keys(row_to_json(t)) FROM
(SELECT * FROM table1
LEFT JOIN table2 ON table1.id = table2.tbl1_id LIMIT 1) t;
This will give you the name of every column returned for a single row. Without the LIMIT you would get the columns repeated for every row returned. If you wanted to see the values returned as well you can get more complex:
WITH t as
(SELECT * FROM table1
LEFT JOIN table2 ON table1.id = table2.tbl1_id LIMIT 1)
SELECT json_data.key, json_data.value
FROM t, json_each_text(row_to_json(t)) AS json_data;
Both these queries will return all the columns even if they are named the same. If all you want is a list of unique column names, you can utilize hstore:
CREATE EXTENSION hstore; --Create the extension if you need it.
SELECT akeys(hstore(t)) as array_of_columns
FROM
(SELECT * FROM table1
LEFT JOIN table2 ON table1.id = table2.tbl1id LIMIT 1) t;
Maybe there is a less hacky way, but I think this should work:
create table query_column_sample from (your query where 1=2);
SELECT column_name
FROM information_schema.columns
WHERE table_name = 'query_column_sample'
Querying tables returns data. Querying the information schema returns metadata. Column names are metadata.
SELECT 'table1', column_name
FROM information_schema.columns
WHERE table_catalog = 'database_name'
AND table_schema = 'schema_name'
AND table_name = 'table1'
UNION ALL
SELECT 'table2', column_name
FROM information_schema.columns
WHERE table_catalog = 'database_name'
AND table_schema = 'schema_name'
AND table_name = 'table2';
"schema_name" is probably public. But be warned that you can have multiple tables with the same name, as long as they are in different schemas. (You could have "public.table1" and "private.table1".) You can also have multiple tables with the same name in different databases. You need to specify all three values--database name, schema name, table name--to be sure of getting the right data.
If I had to do this in production I'd probably output more data. I'd also probably include the column "ordinal_position", and sort on it. Sorting by "ordinal_position" will order column names as they appear in the current table definition.
SELECT table_catalog
, table_schema
, table_name
, column_name
, ordinal_position
FROM information_schema.columns
WHERE table_catalog = 'sandbox'
AND table_schema = 'public'
AND table_name IN ('table1', 'table2')
ORDER BY table_catalog
, table_schema
, table_name
, ordinal_position;
The only reasonable approach I can come up with is to do something like this. Schema location plays into this, but I'm just posting the basic idea. SQL doesn't have reflection at run time unless you go and hit meta data tables, which is what you seem to be trying to achieve here.
SELECT table1.*
INTO x
FROM table1
LEFT JOIN table2
ON table1.id = table2.tbl1_id LIMIT 0;
select *
from information_schema.columns
where table_Name = 'x';
Also interesting enough while traveling the Internets over lunch I ran into this. Works with PostgreSQL 8.2.0 or higher.
https://github.com/theory/colnames/tree/master/test/sql

Where function on a virtual column in a union query

I am new to sql and I need a little help. I have got a union query with 3 tables. I have got a virtual column so I can tell which table each row is from. I would like to be able to filter this virtual column to show only rows from a specific table.
I am using Microsoft Access and this is what I have so far:
SELECT Table1 as Table_Name, Table1.1
FROM Table1
UNION ALL
SELECT Table2 as Table_Name, Table2.1
FROM Table2
UNION ALL
SELECT Table3 as Table_Name, Table3.1
FROM Table3
UNION ALL
WHERE Table_Name = Form1.TextBox
ORDER BY Table1.1;
I am trying to link this to a listbox on a form and then have some textboxs to filter results.
How about:
SELECT * FROM
( SELECT Table1 as Table_Name, Table1.1
FROM Table1
UNION ALL
SELECT Table2 as Table_Name, Table2.1
FROM Table2
UNION ALL
SELECT Table3 as Table_Name, Table3.1
FROM Table3 ) q
WHERE Table_Name = Forms!Form1!TextBox
ORDER BY Table1.1;
See: http://access.mvps.org/access/forms/frm0031.htm

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))