Find Columns whose values are distinct in two tables without union - sql-server

I have two tables having same columns.I want to get those columns whose values are distinct in both tables.How Can I achieve this?please help.Iam stuck.
imageid is primary key in both tables.Its not necessary that imageids present in first table should be present on second table.
first table
imageid name id
1 priya 001
2 neha 002
3 divya 003
4 santo 004
second table
imageid name id
1 priy 001
2 neha 003
4 santo 004
Result
imageid firstdata seconddata columnname
1 priy priya name
2 002 003 id
I have tried this-
select t1.imageid, t1.name as firstdata, t2.name as seconddata, 'name' as colname
from t1 join
t2
on t1.imageid = t2.imageid
where t1.name <> t2.name
union all
select t1.imageid, t1.id as firstdata, t2.id as seconddata, 'id'
from t1 join
t2
on t1.imageid = t2.imageid
where t1.id <> t2.id;
Actually I Have 136 columns and I want query to be optimized.

Related

Sqlserver minus with unmatched columns

I have two tables with different columns and want intersect records.
Table1:
Id name age
1 AAA 20
2 AAA 30
3 BBB 25
4 BBB 30
Table2:
name age
AAA 20
BBB 30
Expect Output:(Table2 - Table1)
Id name age
2 AAA 30
3 BBB 25
You can use NOT EXISTS with a correlated subquery to check that no tuple (name, age) with identical values exists.
SELECT *
FROM table1 t1
WHERE NOT EXISTS (SELECT *
FROM table2 t2
WHERE t2.name = t1.name
AND t2.age = t1.age);
Use Right Join
SELECT DISTINCT Table1.Id, Table1.Name, Table1.Age
FROM Table2 RIGHT JOIN Table1 ON Table1.Name = Table2.Name AND Table1.Age = Table2.Age
WHERE Table2.Name IS NULL
FIDDLE DEMO

SQL Server join two columns both ID of a table with another table's primary Key Column

I was wondering if there is an easy way of joining these two tables.
Table1
Name FromCountryID ToCountryID
------------------------------
sam 1 2
lee 3 4
john 2 1
Table2:
CountryID CountryName
1 USA
2 UK
3 Canada
4 Nepal
You need to join the same table twice with different alias names
select t1.name,
fromTab.countryName as FromCountry,
toTab.countryName as ToCountry
from table1 t1
left join table2 fromTab on fromTab.countryId = t1.fromCountryId
left join table2 toTab on toTab.countryId = t1.toCountryId
SELECT * FROM Table1 INNER JOIN Table2 ON Table2.CountryID = Table1.FromCountryID

Stored Proc to insert rows using Joins

I have 2 tables having IP_Address as common column. My requirement is to get the IP_Address and its associated details in table 1 that are for last 90 days and are not in table 2 and insert the delta in a new table on an nightly basis
DB used: oracle 11g
Table 3 should contain 1 record per IP_Address from Table 1 that are not in Table 2
Table 1
--------------------------------------------------
IP_Address Store_name source TRANS_INIT_TIME
--------------------------------------------------
192.168.0.1 abc e 16-06-29 05:49:16.775265000
192.168.0.1 abc e 16-07-01 07:44:29.019723000
192.168.0.2 ghi b 16-07-06 10:53:54.588610000
192.168.0.2 ghi b 16-07-12 04:04:20.293644000
192.168.0.3 hjg e 16-07-12 03:54:36.024915000
192.168.0.3 hjg e 16-07-15 03:46:27.712961000
192.168.0.4 uiu e 16-09-12 08:57:48.360136000
Table 2
--------------------------
IP.Address loc name
--------------------------
192.168.0.2 hjh uiui
Table 3
--------------------------------
IP_Address Store_name source
-------------------------------
I have prepared join to get the unique IP_Address from table1.
SELECT DISTINCT T1.IP_ADDRESS
FROM Table1 T1
LEFT JOIN TABLE2 T2
ON T1.IP_ADDRESS= T2.IP_ADDRESS
WHERE T1.TRANS_INIT_TIME BETWEEN SYSDATE-90 AND SYSDATE
AND T2.IP_ADDRESS IS NULL
AND T1.IP_ADDRESS IS NOT NULL;
I am struck here on how to get the first row data for these returns IPs and insert them in table 3 through procedure. can anyone help no this ?
Expected Result:
Table 3
--------------------------------
IP_Address Store_name source
-------------------------------
192.168.0.1 abc e
192.168.0.2 ghi b
192.168.0.3 hjg e
192.168.0.4 uiu e
In your case is enough test only the left join key column that is null (this mean that this key don't match with the key form the main table
and for insert you can use an insert select
INSERT INTO Table3 (IP_ADDRESS, Store_name, source)
SELECT DISTINCT T1.IP_ADDRESS, min(T1.Store_name), min(T1.Source)
FROM Table1 T1
LEFT JOIN TABLE2 T2
ON T1.IP_ADDRESS= T2.IP_ADDRESS
WHERE T1.TRANS_INIT_TIME BETWEEN SYSDATE-90 AND SYSDATE
and AND T2.IP_ADDRESS IS NULL
group by T1.IP_ADDRESS
You want the IP_ADDRESS to be unique in the result set but you haven't indicated which row you want for store_name and source. Just pick one randomly maybe? I'm not sure which one you want but here are three different ways to get that table3 you want.
Using an aggregate so you can group by IP_ADDRESS and correlated subquery:
SELECT T1.IP_ADDRESS, MAX(T1.STORE_NAME) AS STORE_NAME, MAX(T1.SOURCE) AS SOURCE
FROM Table1 T1
WHERE NOT EXISTS (SELECT NULL
FROM TABLE2 T2
WHERE T1.IP_ADDRESS = T2.IP_ADDRESS)
GROUP BY T1.IP_ADDRESS
ORDER BY T1.IP_ADDRESS;
Using an aggregate and a left outer join:
SELECT T1.IP_ADDRESS, MAX(T1.STORE_NAME) AS STORE_NAME, MAX(T1.SOURCE) AS SOURCE
FROM Table1 T1
LEFT OUTER JOIN TABLE2 T2 ON T1.IP_ADDRESS = T2.IP_ADDRESS
WHERE T2.IP_ADDRESS IS NULL
GROUP BY T1.IP_ADDRESS
ORDER BY T1.IP_ADDRESS;
Using an analytical function and correlated subquery:
SELECT SUB.IP_ADDRESS, SUB.STORE_NAME, SUB.SOURCE
FROM (
SELECT T1.IP_ADDRESS, T1.STORE_NAME, T1.SOURCE, ROW_NUMBER() OVER (PARTITION BY T1.IP_ADDRESS) AS ROWNUMBER
FROM Table1 T1
WHERE NOT EXISTS (SELECT NULL
FROM TABLE2 T2
WHERE T1.IP_ADDRESS = T2.IP_ADDRESS)
) AS SUB
WHERE SUB.ROWNUMBER = 1
ORDER BY SUB.IP_ADDRESS;

SQL Server Average Query

Can somebody help me about how to query the average of this?
I have this table.
teacher | class | students | rating
-----------------------------------
T1 1 001 6
T1 1 002 6
T1 2 003 1
T1 3 004 1
T2 1 001 6
T2 1 002 6
T2 2 003 1
T2 3 004 1
if I do Select teacher, class, avg(rating) from table group by teacher, class then I get this:
teacher | class | rating
------------------------
T1 1 6
T1 2 1
T1 3 1
T2 1 6
T2 2 1
T2 3 1
what I want to do is get the average rating of that result and group it by teacher which is:
teacher | rating
------------------------
T1 2.66667
T2 2.66667
because if i do Select avg(rating) from table group by teacher, I get
teacher | rating
------------------------
T1 3.5
T2 3.5
You can do this:
SELECT teacher,avg(avgrating) as avgrating
FROM
(Select teacher, class, avg(rating) avgrating
from TableName
group by teacher, class) Temp
GROUP BY teacher
Result:
TEACHER AVGRATING
T1 2.666666
T2 2.666666
Sample result in SQL Fiddle.
OR:
SELECT T1.teacher,avg(T2.avgrating) as rating
FROM TableName T1 JOIN
(SELECT teacher,class,avg(rating) as avgrating
FROM TableName T2
GROUP BY teacher,class) T2 ON T1.teacher=T2.teacher
GROUP BY T1.teacher
SQL Fiddle.
use a nested select:
select teacher , avg(avgr) from
(Select teacher, class, avg(rating) avgr from table group by teacher, class) qry
group by teacher

How to get column of table with a self-referencing foreign key?

I have a table structure shown below:
Id Name Sal ManagerId
1 a 5000 2
2 b 7000 3
3 c 6000 1
I need output like this
Id Name Sal Manager
1 a 5000 b
2 b 7000 c
3 c 6000 a
How can i do that?
You have to use a self-JOIN to link one table to itself:
SELECT t1.Id, t1.Name, t1.Sal, t2.ManagerName AS Manager
FROM TableName t1 INNER JOIN TableName t2
ON t1.ManagerID = t2.Id
If ManagerId is nullable you might want to use an OUTER JOIN:
SELECT t1.Id, t1.Name, t1.Sal, COALESCE(t2.ManagerName, '<no manager>') AS Manager
FROM TableName t1 LEFT OUTER JOIN TableName t2
ON t1.ManagerID = t2.Id

Resources