how to find collegue Id in table - sql

i have one table as Employee that have two column Id and Branch. i have to find its collegue Id except his own id from table without using subquery.
Id Branch
==============
1 Delhi
2 Mumbai
3 Delhi
4 Delhi
5 Mumbai
6 Mumbai
if i enter e.g. 3 then my answer has to be 1 and 4.

Without a subquery means with a self join:
select tt.*
from tablename t inner join tablename tt
on t.Branch = tt.Branch and tt.id <> t.id
where t.id = 3
See the demo.

use self join
select t2.id from table_name t1
join table_name t2 on t1.Branch=t2.Branch
where t1.id=3 and t2.id!=3
for data preparation easily i used CTE version below with result
with cte as
(
select 1 as id, 'Delhi' as b
union all
select 2, 'Mumbai'
union all
select 3 , 'Delhi'
union all
select 4 , 'Delhi'
) select t2.id from cte t1 join cte t2 on t1.b=t2.b
where t1.id=3 and t2.id!=3
demo link
here is the output
id
1
4

This query should give you the answer you're after:
SELECT E1.Id
FROM Employee E1
INNER
JOIN Employee E2
ON E1.[Branch] = E2.[Branch]
WHERE E2.Id = 3
AND E1.Id <> 3
It works by joining the Employee table onto itself, by Branch and then:
WHERE E2.Id = 3 - Where the Employee is Id # 3
AND E1.Id <> 3 - excluding any records from the original Employee table where Id is 3
Here's the script I used to create your test data (in SQL Server) for the purposes of validating the query:
CREATE TABLE [Employee]
(
[Id] INT,
[Branch] NVARCHAR(10)
)
INSERT
INTO [Employee]
(
Id,
[Branch]
)
VALUES (1, 'Delhi'),
(2, 'Mumbai'),
(3, 'Delhi'),
(4, 'Delhi'),
(5, 'Mumbai'),
(6, 'Mumbai')

Related

Find exactly equal rows in 2 tables, both in terms of value and number

I have two Table, that both of them have 2 field (provinceid,cityid)
i want to find provinceid that have exactly the same cityid in this two table.
for example i have this tables:
table1:
provinceid
cityid
1
1
1
2
2
3
2
4
3
6
table2:
provinceid
cityid
1
1
1
5
2
3
2
4
3
6
3
7
i want a query that just return provinceid =2 and city id =3 and 4.
i try this query and it is right. but i want a better query:
select provinceid ,t1.cityid
from t1
left join t2 on t1=provinceid=t2.provinceid and t1.cityid=t2.cityid
where t2.provinceid is not null and t2.cityid is not null
and t1.provinceid not in (select provinceid
from t2
left join t1 on t1=provinceid=t2.provinceid and t1.cityid=t2.cityid
where t1.provinceid is not null and t1.cityid is not null)
thank you
Try this :
select t1.provinceid ,t1.cityid
from table1 t1 join table2 t2
on t1.provinceid=t2.provinceid
and t1.cityid=t2.cityid
and t1.provinceid in (
select distinct(t1.provinceid)
from
(select provinceid, count(provinceid) as cnt from table1 group by provinceid) as t1
cross join
(select provinceid ,count(provinceid) as cnt from table2 group by provinceid) as t2
where t1.cnt = t2.cnt);
Output:
provinceid
cityid
1
1
2
3
2
4
The simplest method for an exact match is to use string aggregation. The exact syntax varies by database, but in Standard SQL this looks like:
select t1.provinceid, t2.provinceid
from (select provinceid,
listagg(cityid, ',') within group (order by cityid) as cities
from t1
group by provinceid
) t1 join
(select provinceid,
listagg(cityid, ',') within group (order by cityid) as cities
from t2
group by provinceid
) t2
on t1.cities = t2.cities;
If you want the provinceids to be the same as well, just add t1.provinceid = t2.provinceid to the on clause.
Or, if you want the provinceids to be the same, you can use full join instead:
select provinceid
from t1 full join
t2
using (provinceid, cityid)
group by provinceid
having count(*) = count(t1.cityid) and count(*) = count(t2.cityid);
Besides match in provid and cityid, we are looking for exactly matching sets of records as well. There might be many different methods to this. I prefer to have string comparison for list of cities for each provide with addition to provide and cityid match clause to remove other sets of provide and cityid which are available in tables but not the exact row match.
WITH table1 AS(
SELECT 1 AS PROVID, 1 AS CITYID FROM DUAL UNION ALL
SELECT 1 AS PROVID, 2 AS CITYID FROM DUAL UNION ALL
SELECT 2 AS PROVID, 3 AS CITYID FROM DUAL UNION ALL
SELECT 2 AS PROVID, 4 AS CITYID FROM DUAL UNION ALL
SELECT 3 AS PROVID, 6 AS CITYID FROM DUAL
),
table2 AS (
SELECT 1 AS PROVID, 1 AS CITYID FROM DUAL UNION ALL
SELECT 1 AS PROVID, 5 AS CITYID FROM DUAL UNION ALL
SELECT 2 AS PROVID, 3 AS CITYID FROM DUAL UNION ALL
SELECT 2 AS PROVID, 4 AS CITYID FROM DUAL UNION ALL
SELECT 3 AS PROVID, 6 AS CITYID FROM DUAL UNION ALL
SELECT 3 AS PROVID, 7 AS CITYID FROM DUAL
),
listed_table1 AS (
SELECT
a.provid,
listagg(cityid,',') within GROUP (ORDER BY cityid) list_city
FROM table1 a
GROUP BY a.provid
),
listed_table2 AS (
SELECT
a.provid,
listagg(cityid,',') within GROUP (ORDER BY cityid) list_city
FROM table2 a
GROUP BY a.provid
)
SELECT
t1.provid, t1.cityid
FROM
(SELECT x.*, x1.list_city FROM table1 x, listed_table1 x1 WHERE x.provid = x1.provid) t1,
(SELECT y.*, y1.list_city FROM table2 y, listed_table2 y1 WHERE y.provid = y1.provid) t2
WHERE t1.provid = t2.provid AND t1.cityid = t2.cityid AND t1.list_city = t2.list_city
;
You can use (union ..)except (inner join..) to detect non-matches. Step by step
with u12 as (
select PROVID, CITYID from table1
union
select PROVID, CITYID from table2
),
c12 as (
select t1.PROVID, t2.CITYID
from table1 t1
join table2 t2 on t1.PROVID=t2.PROVID and t1.CITYID=t2.CITYID
),
nonMatch as (
select distinct PROVID
from (
select PROVID, CITYID from u12
except
select PROVID, CITYID from c12
) t
)
select *
from table1 t
where not exists (
select 1
from nonMatch n
where n.PROVID = t.PROVID);
If a number of doubles counts then count them first
with t1 as (
select PROVID, CITYID, count(*) n
from table1
group by PROVID, CITYID
),
t2 as (
select PROVID, CITYID, count(*) n
from table2
group by PROVID, CITYID
),
u12 as (
select PROVID, CITYID, n from t1
union
select PROVID, CITYID, n from t2
),
c12 as (
select t1.PROVID, t1.CITYID, t1.n
from t1
join t2 on t1.PROVID = t2.PROVID and t1.CITYID = t2.CITYID and t1.n = t2.n
),
nonMatch as (
select distinct PROVID
from (
select PROVID, CITYID, n from u12
except
select PROVID, CITYID, n from c12
) t
)
select *
from table1 t
where not exists (
select 1
from nonMatch n
where n.PROVID = t.PROVID)
db<>fiddle

How can I override rows from another table?

I have two tables:
TableA
ID Name
-- ----
1 aaa
2 bbb
3 ccc
4 ddd
TableB
ID Name
-- --------
3 WWXXYYZZ
I want to select from both tables, but skip the rows which exist in TableB. The result should look like this:
ID Name
-- --------
1 aaa
2 bbb
3 WWXXYYZZ
4 ddd
I have tried union and join but did not figure out how to achieve this.
-- Did not work
select *
from TableA
union
select *
from TableB
-- Did not work
select *
from
(
select *
from TableA
) x
join
(
select *
from TableB
) y
on x.ID = y.ID
You could left join b on to a, and use coalesce to prefer b's rows:
SELECT a.id, COALESCE(b.name, a.name) AS name
FROM a
LEFT JOIN b ON a.id = b.id
You can do:
select a.id, coalesce(b.name, a.name)
from a left join b on a.id = b.id
One method is union all:
select b.*
from b
union all
select a.*
from a
where not exists (select 1 from a where a.id = b.id);
You can also choose from a and override with values from b:
select a.id, coalesce(b.name, a.name) as name
from a left join
b
on a.id = b.id;
A more complex method uses ROW_NUMBER which might be necessary if your query is significantly more complex than shown. It also handled the case where a row exists in TableB but not TableA (which is not clear from your question).
DECLARE #TableA TABLE (id INT, [Name] VARCHAR(12));
DECLARE #TableB TABLE (id INT, [Name] VARCHAR(12));
INSERT INTO #TableA (id, [Name])
VALUES
(1, 'aaa'),
(2, 'bbb'),
(3, 'ccc'),
(4, 'ddd');
INSERT INTO #TableB (id, [Name])
VALUES
(3, 'WWXXYYZZ'),
(5, 'TTTGGG');
SELECT id, [Name]
FROM (
SELECT id, [Name]
, ROW_NUMBER() OVER (PARTITION BY id ORDER BY [Priority] DESC) Rn
FROM (
SELECT id, [Name], 0 [Priority]
FROM #TableA
UNION ALL
SELECT id, [Name], 1 [Priority]
FROM #TableB
) X
) Y
WHERE Rn = 1;
Returns:
1 aaa
2 bbb
3 WWXXYYZZ
4 ddd
5 TTTGGG

Delete Rows based on two columns

How can I delete rows based on just two column conditions.
Example
Table 1
id name phone
1 aa 123
1 aa 345
1 bb 123
2 aa 456
1 NULL 123
1 123
My Expected output
id name phone
1 bb 123
2 aa 456
My condition to delete: if id and name is same, delete the rows
If one of the value in a condition is null or blank it should also delete the row as given in the input.
Delete from table1 t where exists (
Select * from
(Select id, name from table1 group by id, name having count(*) > 1) t2 where t.id = t2.id and t.name = t2.name)
This should do what you want. You can do the select first for testing purposes, then remove the Select and uncomment out the delete.
-- This joins on the table the set of data that has more then 1 row with duplicate IDs, and names. Then you can delete from here.
--DELETE t1
SELECT *
FROM Table1 T1
INNER JOIN (
-- this gets all the records that have more then 1 ID and Name that are the same.
SELECT ID, name
FROM Table1
GROUP BY ID, name
HAVING COUNT(*) > 1
) ToDelete ON T1.ID = ToDelete.ID
AND T1.name = ToDelete.name
create table #tablea (
id int,
name varchar(3),
phone int
)
insert into #tablea (id, name, phone)
values
(1,'aa','123'),
(1,'aa','345'),
(1,'bb','123'),
(2,'aa','456')
select * from #tablea
delete a
from #tablea a
inner join (
select id, name
from #tablea
group by id, name
having COUNT(*) > 1
) b on a.id = b.id and a.name = b.name
select * from #tablea
drop table #tablea

SQL Left JOINING 3 Tables

I have 1 Table:
Contacts (ID integer, Name text, ATT_ID integer)
My Table is filled with these values:
(1, 'Alice', 1)
(2, 'Bob', 1)
(3, 'Carol', 1)
(4, 'Dave', 4)
(5, 'Eve', 4)
(6, 'Frank', 6)
The goal is to join these Contacts ID with the paired ATT_ID.
This is my current SQL-Code:
SELECT t1.ID as ID, t1.Name , tt.Name , tt2.Name
FROM Contacts as t1
LEFT JOIN (
SELECT MIN(t2.ID), t2.Name, t2.ATT_ID FROM Contacts as t2
WHERE t2.ID <> t2.ATT_ID)
AS tt ON t1.ID = tt.ATT_ID
LEFT JOIN (
SELECT MAX(t3.ID), t3.Name, t3.ATT_ID FROM Contacts as t3
WHERE t3.ID <> t3.ATT_ID)
AS tt2 ON t1.ID = tt2.ATT_ID
WHERE t1.ID = t1.ATT_ID;
and my Result is:
Alice | Bob | null
Dave | null | Eve
Frank | null | null
But the desired result should look like this:
Alice | Bob | Carol
Dave | Eve | null
Frank | null | null
How can I accomplish this?
Assuming your RDBMS supports Window Functions...
This can be accomplished by generating a row number of for each sub group and only displaying the smallest row number.
This also assumes you have no more than 3 in each group.
The below is ORACLE specific but should work with MS SQL and Postgresql and DB2. It will not work with MySQL as window functions are not supported.
Note the with block as built will only work in ORACLE.
With contacts (ID, Name, ATT_ID) as (
Select 1, 'Alice', 1 from dual union all
Select 2, 'Bob', 1 from dual union all
Select 3, 'Carol', 1 from dual union all
Select 4, 'Dave', 4 from dual union all
Select 5, 'Eve', 4 from dual union all
Select 6, 'Frank', 6 from dual)
--FROM HERE ON should work if window functions supported.
Select * from (
Select T1.Name N1, T2.Name N2, T3.Name N3, Row_Number() Over (partition by T1.ATT_ID order by T1.ID) rn
FROM Contacts T1
LEFT JOIN Contacts T2
on T1.ATT_ID = T2.ATT_ID
and T1.ID < T2.ID
LEFT JOIN contacts T3
on T2.ATT_ID = T3.ATT_ID
and T2.ID < T3.ID
and T1.ID < T3.ID) B
WHERE RN =1

SQL Query to get name that appear twice

I have the below Table
Table1
Emp ID | Emp Name
001 | ABC
002 | DEF
003 | GHI
004 | ABC
005 | XYZ
I am trying to get EMP ID and Emp Name where Emp Name is same but Emp ID is different. There is primary key in the table
Here the output will be
Emp ID | Emp Name
001 | ABC
004 | ABC
You didn't specify your DBMS, so this is ANSI SQL:
select emp_id, emp_name
from (
select emp_id, emp_name,
count(*) over (partition by emp_name) as name_count
from employee
) t
where name_count > 1^;
Group by Emp_Name, select records having count Emp_ID more than one and then select all records from table having such Emp_Name:
select Emp_ID, Emp_Name
from Table1
where Emp_Name in
(
select Emp_Name
from Table1
group by Emp_Name
having count(Emp_ID) > 1
)
Please try with below.
SELECT T1.* FROM
TABLE1 T1
JOIN
(
SELECT EMP_NAME, COUNT(EMP_ID) FROM TABLE1 GROUP BY EMP_NAME HAVING COUNT(EMP_ID) > 1
) T2 ON T1.EMP_NAME = T2.EMP_NAME
I have the same problem yesterday :) and i believe below code will give you what you want.
Use INNER JOIN to make a self join query, then use HAVING clause.
CREATE TABLE #Table1 (Emp_ID int, Emp_Name varchar(50))
INSERT INTO [#Table1]
(
[Emp_ID],
[Emp_Name]
)
SELECT '001','ABC'
UNION ALL SELECT '002','DEF'
UNION ALL SELECT '003','GHI'
UNION ALL SELECT '004','ABC'
UNION ALL SELECT '005','XYZ'
SELECT [t1].[Emp_ID], [t1].[Emp_Name] FROM [#Table1] t1
INNER JOIN
(
SELECT [#Table1].[Emp_Name] FROM [#Table1]
GROUP BY [#Table1].[Emp_Name]
HAVING COUNT([#Table1].[Emp_ID]) > 1
) t2
ON [t1].[Emp_Name] = [t2].[Emp_Name]
DROP TABLE [#Table1]
Below is the result:
Emp_ID Emp_Name
1 ABC
4 ABC
SQL Fiddle Demo - Click here
Another EXISTS version, but without any aggregating:
select t1.*
from tablename t1
where exists (select 1 from tablename t2
where t2.Emp_Name = t1.Emp_Name
and t2.Emp_ID <> t1.Emp_ID)
May speed up things a bit. Otherwise I'd try self join version:
select t1.*
from tablename t1
join tablename t2 on t2.Emp_Name = t1.Emp_Name
and t2.Emp_ID <> t1.Emp_ID
Perhaps, depending on data, you need to do SELECT DISTINCT.