Suppose I have one table with the following values and columns:
ID1 | ID2
1 | 1
2 | 1
3 | 1
4 | 1
4 | 2
3 | 3
4 | 3
4 | 4
4 | 4
I'd like to retrieve the ID2 values that belong exclusively to records where ID1 = 4. So for the above example, I'd like to see the following response:
ID1 | ID2
4 | 2
4 | 4
Try working it out contrapositively like this.
Finding all elements where ID1 is only 4 is the same as finding all elements that don't not have ID1 = 4.
CREATE TABLE #temp (ID1 NVARCHAR(10), ID2 NVARCHAR(10))
INSERT INTO #temp(ID1,ID2) VALUES (N'1',N'1')
INSERT INTO #temp(ID1,ID2) VALUES (N'2',N'1')
INSERT INTO #temp(ID1,ID2) VALUES (N'3',N'1')
INSERT INTO #temp(ID1,ID2) VALUES (N'4',N'1')
INSERT INTO #temp(ID1,ID2) VALUES (N'4',N'2')
INSERT INTO #temp(ID1,ID2) VALUES (N'3',N'3')
INSERT INTO #temp(ID1,ID2) VALUES (N'4',N'3')
INSERT INTO #temp(ID1,ID2) VALUES (N'4',N'4')
INSERT INTO #temp(ID1,ID2) VALUES (N'4',N'4')
SELECT * FROM #temp AS t
SELECT DISTINCT * FROM #temp AS t
WHERE id2 NOT IN (SELECT ID2 FROM #temp AS t WHERE ID1 <> 4)
These queries will probably be useful to you for the more general cases (and by general I mean when ID1 is something other than 4):
select distinct t1.id1, t1.id2
from T as t1
where not exists (
select 1
from T as t2
where t2.ID1 <> t1.ID1 and t2.ID2 = t1.ID2
)
select t1.id1, count(distinct t1.id2)
from T as t1
where not exists (
select 1
from T as t2
where t2.ID1 <> t1.ID1 and t2.ID2 = t1.ID2
)
group by t1.id1
You can also do this:
select 4,id2 from
(select distinct ID1 , ID2 from t) t1
group by id2
having count(*)=1
There are a few ways to do this:
SELECT t1.id1, t1.id2
FROM mytable t1
WHERE t1.id1 = 4
AND NOT EXISTS ( SELECT 1 FROM mytable t2
WHERE t2.id2 = t1.id2
AND t2.id1 != 4 );
or:
SELECT id1, id2 FROM (
SELECT id1, id2
FROM mytable
GROUP BY id1, id2
HAVING COUNT(*) = 1
) WHERE id1 = 4;
or:
SELECT id1, id2 FROM (
SELECT id1, id2, COUNT(*) OVER ( PARTITION BY id2 ) AS cnt
FROM mytable
) WHERE id1 = 4
AND cnt = 1;
Related
I've a table where I want to append name column if id1 and id2 column have same values.
http://sqlfiddle.com/#!3/8be48/1
Input table
id1 id2 name
1 1 a
1 1 b
2 2 c
2 2 c
3 3 d
3 3 e
3 3 f
Expected Output
id1 id2 name
1 1 a | b
2 2 c | c
3 3 d | e | f
I tried groping the id1 and id2 together and concatenating name column but it didn't work out.
select id1, id2, name + ' | ' + name
from testdata
group by id1, id2;
Use STUFF String function :
CREATE TABLE #table(id1 INT, id2 INT , name VARCHAR(10))
INSERT INTO #table(id1 , id2 ,name )
SELECT 1,1,'a' UNION ALL
SELECT 1,1,'b' UNION ALL
SELECT 2,2,'c' UNION ALL
SELECT 2,2,'c' UNION ALL
SELECT 3,3,'d' UNION ALL
SELECT 3,3,'e' UNION ALL
SELECT 3,3,'f'
SELECT T1.id1 id1, T1.id2 id2 , STUFF( ( SELECT ' | ' + name FROM #table T2
WHERE T1.id1 = T2.id1 AND T1.id2 = T2.id2 FOR XML PATH('') ) ,1,2,'')
FROM #table T1
GROUP BY id1 , id2
I have two tables :-
Table1:-
ID1
1
1
1
1
4
5
Table2:-
Id2
2
2
1
1
1
8
I want to show all the ID2 from table2 which are present in ID1 of table1 by using joins
I used :-
select ID2 from Table2 t2 left join Table1 t1
on t2.Id2=t1.Id1
But this was giving repeated result as :-
Id2
1
1
1
1
1
1
1
It should show me 1 as 3 times only as it is present in Table2 3 times.
Please help.
You're matching the value 1 with 4 rows on Table1 and 3 rows on Table2 that's why you're seeing 12 rows. You need an additional JOIN condition. You can add a ROW_NUMBER and do an INNER JOIN to achieve your desired result.
WITH Cte1 AS(
SELECT *,
rn = ROW_NUMBER() OVER(PARTITION BY Id1 ORDER BY (SELECT NULL))
FROM Table1
),
Cte2 AS(
SELECT *,
rn = ROW_NUMBER() OVER(PARTITION BY Id2 ORDER BY (SELECT NULL))
FROM Table2
)
SELECT c2.Id2
FROM Cte2 c2
INNER JOIN Cte1 c1
ON c1.Id1 = c2.Id2
AND c1.rn = c2.rn
However, you can achieve the desired result without using a JOIN.
SELECT *
FROM Table2 t2
WHERE EXISTS(
SELECT 1 FROM Table1 t1 WHERE t1.Id1 = t2.Id2
)
It's the expected behavior of Join Operation. It will match every row from the two tables, so you will get 12 rows containing value 1 in result of join query.
You can use below query to get desired result.
select ID2 from Table2 t2 WHERE ID2 IN (SELECT ID1 FROM Table1 t1)
select id2 from table2 t2 where exists ( select 1 from table1 t1 where t1.id1 = t2.id2)
Your join logic works fine, the problem is each of your ID2 is matching against all ID1s. A simple solution would be to join with a table of distinct ID1s to avoid this duplication.
select
t2.ID2
from Table2 t2
left join (select distinct * from Table1) t1
on t1.Id1=t2.Id2
where t1.ID1 is not null
;
Here is a functional example
This will select your entire ID2 list with ID1 populated in a column. ID1 is null where there was no match. Select your ID2 column from this table but just don't pull null values (with where clause):
I have a query that groups easily. I need to get the groups that have exactly the same records to another table (relationship).
I'm using ANSI-SQL under SQL Server, but I accept an answer of any implementation.
For example:
Table1:
Id | Value
---+------
1 | 1
1 | 2
1 | 3
2 | 4
3 | 2
4 | 3
Table2:
Value | ...
------+------
1 | ...
2 | ...
3 | ...
In my example, the result is:
Id |
---+
1 |
How imagined that it could be the code:
SELECT Table1.Id
FROM Table1
GROUP BY Table1.Id
HAVING ...? -- The group that has exactly the same elements of Table2
Thanks in advance!
You can try the following:
select t1.Id
from Table2 t2
join Table1 t1 on t1.value = t2.value
group by t1.Id
having count(distinct t1.value) = (select count(*) from Table2)
SQLFiddle
To get the same sets use an inner join:
SELECT Table1.Id
FROM Table1
INNER JOIN table2 ON table1.id=table2.id
GROUP BY Table1.Id
HAVING ...? --
CREATE TABLE #T1 (ID INT , [Values] INT) INSERT INTO #T1 VALUES (1,1),(1,2),(1,3),(2,4),(2,5),(3,6)
CREATE TABLE #T2 ([Values] INT) INSERT INTO #T2 VALUES (1),(2),(3),(4)
SELECT * FROM #T1
SELECT * FROM #T2
SELECT A.ID
FROM
( SELECT ID , COUNT(DISTINCT [Values]) AS Count FROM #T1
GROUP BY ID
) A
JOIN
(
SELECT T1.ID, COUNT(DISTINCT T2.[Values]) Count
FROM #T1 T1
JOIN #t2 T2
ON T1.[Values] = T2.[Values]
GROUP BY T1.ID
) B
ON A.ID = B.ID AND A.Count = B.Count
I was working on preparing a query where I was stuck.
Consider tables below:
table1
id key col1
-- --- -----
1 1 abc
2 2 d
3 3 s
4 4 xyz
table2
id col1 foreignkey
-- ---- ----------
1 12 1
2 13 1
3 14 1
4 12 2
5 13 2
Now what I need is to select only those records from table1 for which the corresponding entries in table2 does not have say col1 value as 12.
So the challenge is after applying join even though it will skip for value 1 corresponding to col1 equal to 12 it still has another multiple rows whose values are say 13, 14 for which also they have same foreignkey. Now what I want is if there is a single row having value 12 then it should not pick that id at all from table1.
How can I form a query with this?
The output which i need is say from above table structure i want to get those records from table1 for which col1 value from table2 does not have value as 14.
so my query should return me only row 2 from table1 and not row 1.
Another way of doing that. The first two queries are just for making the sample data.
;WITH t1(id ,[key] ,col1) AS
(
SELECT 1 , 1 , 'abc' UNION ALL
SELECT 2 , 2 , 'd' UNION ALL
SELECT 3 , 3 , 's' UNION ALL
SELECT 4 , 4 , 'xyz'
)
,t2(id ,col1, foreignkey) AS
(
SELECT 1 , 12 , 1 UNION ALL
SELECT 2 , 13 , 1 UNION ALL
SELECT 3 , 14 , 1 UNION ALL
SELECT 4 ,12 , 2 UNION ALL
SELECT 5 ,13 , 2
)
SELECT id, [key], col1
FROM t1
WHERE id NOT IN (SELECT t2.Id
FROM t2
INNER JOIN t1 ON t1.Id = t2.foreignkey
WHERE t2.col1 = 14)
This is a typical case for NOT EXISTS:
SELECT id, [key], col1
FROM table1 t1
WHERE NOT EXISTS (SELECT 1
FROM table2 t2
WHERE t2.foreignkey = t1.id AND t2.col1 = 14)
The above query will not select a row from table1 if there is a single correlated row in table2 having col1 = 14.
Output:
id key col1
-------------
2 2 d
3 3 s
4 4 xyz
If you want to return records that, in addition to the criterion set above, also have correlated records in table2, then you can use the following query:
SELECT t1.id, MAX(t1.[key]) AS [key], MAX(t1.col1) AS col1
FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.foreignkey
GROUP BY t1.id
HAVING COUNT(CASE WHEN t2.col1 = 14 THEN 1 END) = 0
Output:
id key col1
-------------
2 2 d
You can also achieve the same result with the second query using a combination of EXISTS and NOT EXISTS:
SELECT id, [key], col1
FROM table1 t1
WHERE EXISTS (SELECT 1
FROM table2 t2
WHERE t2.foreignkey = t1.id)
AND
NOT EXISTS (SELECT 1
FROM table2 t3
WHERE t3.foreignkey = t1.id AND t3.col1 = 14)
select t1.id,t1.key,
(select ROW_NUMBER() OVER(PARTITION BY col1 ORDER BY col1 DESC) AS Row,* into
#Temp from table1)
from table1 t1
inner join table2 t2 on t1.id=t2.foreignkey
where t2.col1=(select col1 from #temp where row>1)
Have an issue
Examle
ID ID2
1 100
3 100
5 100
1 110
2 110
4 110
select * from table where ID in (1,4) ---executing not correctly
select * from table where ID = '1' and ID = '4' ---not work
I need that ID2 will '110' (select ID2 which have 2 value ID)
Thanks.
If you have few ID's you can use EXISTS:
SELECT ID, ID2
FROM dbo.Table1 t1
WHERE EXISTS
(
SELECT 1 FROM dbo.Table1 t2
WHERE t2.ID=1 AND t2.ID2=t1.ID2
)
AND EXISTS
(
SELECT 1 FROM dbo.Table1 t2
WHERE t2.ID=4 AND t2.ID2=t1.ID2
)
AND ID IN (1, 4)
This returns the two records that have the same ID2 and ID=1 AND ID=4.
ID ID2
1 110
4 110
Demo-Fiddle
SELECT ID FROM (
SELECT ID, COUNT(*) OVER(PARTITION BY ID2) as cnt FROM Table) t
WHERE t.cnt>1