Joining two tables in a select - sql

I have two tables:
TABLE 1
ID VALUE
1 ABC
2 DEF
3 GHI
4 JKL
5 XYZ
TABLE 2
ID T1_ID VALUE
1 1 A
2 1 B
3 2 A
4 3 A
5 3 B
6 4 B
I want to select all rows from TABLE 1 which have a TABLE 2 row for Values A AND B.
This would be rows 1 and 3 (not 2 because it has only A, not 4 because it has only B).
Can I do this without a subquery?
(Note: I also need to query against values in table 1 so I can't just query table 2.)

Tadaaah! Without a subquery.
select distinct
t1.*
from
Table1 t1
inner join Table2 t2a on t2a.t1_ID = t1.ID and t2a.VALUE = 'A'
inner join Table2 t2b on t2b.t1_ID = t1.ID and t2b.VALUE = 'B'

SELECT t1.ID,
t1.VALUE
FROM Table1 t1
JOIN Table2 t2
ON t1.ID = t2.T1_ID
WHERE t2.VALUE IN ( 'A', 'B' )
GROUP BY t1.ID,
t1.VALUE
HAVING COUNT(DISTINCT t2.VALUE) = 2

Related

SQL only join when key matches one criteria

I have two tables that look like the following:
Table 1 (IDs):
ID
1
2
3
4
5
Table 2 (Categories):
ID CAT
1 A
1 B
2 A
3 A
4 B
5 A
5 B
5 C
What I would like to do is join table 2 to table 1 and only keep instances where there is 1) Only one match 2) That match is CAT = A
So my final table would look like:
ID CAT
2 A
3 A
One method is aggregation and having:
select id, max(cat)
from t
group by id
having count(*) = 1 and
max(cat) = 'A';
You can use a subquery with not exists:
select t1.id, t2.cat
from table1 t1
join table2 t2 on t1.id = t2.id
where t2.cat = 'A' and not exists (select 1 from table2 t3 where t3.id = t1.id and t3.cat != 'A');
Output:
id
cat
2
A
3
A

How to find records which ALL values in column are contained in another table?

I have such tables:
Table1
ID | Name
---------
1 Name1
2 Name2
3 Name3
Table2
ID | FindID Table1ID
--------------------
1 1 1
2 2 1
3 1 2
4 2 2
5 1 3
6 2 3
7 3 3
8 1 4
Table3
ID
--
1
2
What I need to do - I need to find all Table 1 Ids which have in Table 2 all Table 3 values as FindId column's values .
For example, if in Table 3 we have 1 and 2, in result it should return
Result
ID
-----
1
2
3
Because Table1.Id = 1 have 1 and 2 in Table 2, same for Table1.Id = 2, and Table1.Id = 3 have 1,2,3.
Table1.Id = 4 has only 1, so it isn't contained in results.
If in Table 3 we have 1,2,3 - then only Table1.Id = 3 will be returned.
I've tried something like
SELECT distinct t1.id FROM Table1 t1
join Table2 t2 on t2.Table1Id = t1.ID
join Table3 t3 on t3.Id = t2.FindId
But it doesn't work.
If I understand correctly, you want all table2.table1id that have all the findIds in table3. If so, aggregation should do what you want:
select t2.table1id
from table2 t2 join
table1 t3
on t2.findid = t3.id
group by t2.table1id
having count(*) = (select count(*) from table3);

How can get a column where my result is 1 2 3 6 7 8 I want to exclude the common IDs from both the table and display the result in one column

Let's say I have Two tables T1 and T2 with ID as the column. For example
T1:ID
1
2
3
4
5
T2:ID
4
5
6
7
8
How can get a column where my result is 1 2 3 6 7 8 I want to exclude the common IDs from both the table and display the result in one column.
Hmmm . . . one method is union all:
select t1.id
from table1 t1
where not exists (select 1 from table2 t2 where t2.id = t1.id)
union all
select t1.id
from table2 t2
where not exists (select 1 from table1 t1 where t2.id = t1.id);
use minus
select id from
(
select id from t1
union
select id from t2
) a
minus select id from (
select id from t1 join t2 on t1.id=t2.id
) b
If your DBMS support FULL OUTER JOIN then i would do :
select coalesce(t1.id, t2.id)
from t1 full outer join
t2
on t2.id = t1.id
where (t1.id is null or t2.id is null);

Aggregate functions as column results from multiple tables

I have the following table structures:
Table1
--------------
Table1Id
Field1
Field2
Table2
------------
Table2Id
Table1Id
Field1
Field2
Table3
-----------
Table3Id
Table1Id
Field1
Field2
I need to be able to select all fields in Table1, count of records in Table2, and count of records in Table3 Where count of records in Table2 > count of records in Table3
Here is an example of expected output with the given data:
Table1 Data
-------------
1 Record1Field1 Record1Feild2
2 Record2Field1 Record2Feild2
3 Record3Field1 Record3Feild2
4 Record4Field1 Record4Feild2
Table2 Data
------------
1 1 Record1Field1 Record1Feild2
2 1 Record2Field1 Record2Feild2
3 2 Record3Field1 Record3Feild2
4 2 Record4Field1 Record4Feild2
5 2 Record5Field1 Record5Feild2
6 4 Record6Field1 Record6Feild2
7 4 Record6Field1 Record6Feild2
8 4 Record6Field1 Record6Feild2
Table3 Data
------------
1 2 Record1Field1 Record1Feild2
2 2 Record2Field1 Record2Feild2
3 3 Record3Field1 Record3Feild2
4 3 Record4Field1 Record4Feild2
5 3 Record5Field1 Record5Feild2
6 4 Record6Field1 Record6Feild2
Desired Results
Table1Id Field1 Field2 Table2Count Table3Count
1 Record1Field1 Record1Field2 2 0
2 Record2Field1 Recird2Field2 3 2
4 Record4Field1 Recird4Field2 3 1
Notice record 3 in Table 1 is not shown because the record count in Table2 is less than the record count in Table3. I was able to make this work using a very ugly query similar to the one below but feel there is a much better way to do this using joins.
SELECT
t1.Table1Id,
t1.Field1,
t1.Field2
(Select Count(Table2Id) From Table2 t2 Where t2.Table1Id = t1.Table1Id) as Table2Count,
(Select Count(Table3Id) From Table3 t3 Where t3.Table1Id = t1.Table1Id) as Table3Count,
From
Table1 t1
Where
(Select Count(Table2Id) From Table2 t2 Where t2.Table1Id = t1.Table1Id) > (Select Count(Table3Id) From Table3 t3 Where t3.Table1Id = t1.Table1Id)
Hard to test it without working examples but something along these lines should be a good starting point.
SELECT
t1.Table1Id,
t1.Field1,
t1.Field2,
COUNT(DISTINCT t2.Table2Id),
COUNT(DISTINCT t3.Table3Id)
From Table1 t1
LEFT OUTER JOIN Table2 t2 ON t1.Table1Id = t2.Table1Id
LEFT OUTER JOIN Table3 t3 ON t1.Table1Id = t3.Table1Id
GROUP BY t1.Table1Id
HAVING COUNT(DISTINCT t2.Table2Id) > COUNT(DISTINCT t3.Table3Id)
You could get all the value in t1 and the data form t2 e t3 for your comparision using a couple of join on grouped values
SELECT
t1.Table1Id
,t1.Field1
,t1.Field2
, tt2.count_t2
, tt3.count_t3
from table1 t1
join (
select Table1Id, count(*) count_t2
From Table2
group by Table1Id
) tt2 on tt2.Table1Id = t1.Table1Id
join (
select Table1Id, count(*) count_t3
From Table3
group by Table1Id
) tt3 on tt3.Table1Id = t1.Table1Id
where tt2.count_t2 < tt3.count_t3 <

UNION ALL Sql query - how to bind three tables

I have the following tables:
T1
ID PRIORITY
1 1
2 1
3 2
4 4
T2
ID SERVICE
1 PSTN
1 ADSL
3 ADSL
T3
ID DEVICE
1 BSC1
3 BSC7
4 BSC7
I want as output
ID PRIORITY SERVICE/DEVICE
1 1 PSTN
1 1 ADSL
1 1 BSC1
2 1
3 2 ADSL
3 2 BSC7
How to bind those tables using UNION ALL? Also I must put WHERE clause for T1 WHERE PRIORITY!=4
Total number in output table for one id should be the summary of T2+T3 (FOR ID=1 2+1=3) but for ID=2 it also SHOULD exist in table output with blank second column.
Thank you
If you are okay using just a UNION and not UNION ALL this should give you what you want
SELECT t1.Id, t1.Priority, COALESCE(t2.Service, '') AS [Service/Device]
FROM t1
LEFT JOIN t2 ON t1.Id = t2.Id
WHERE t1.Priority != 4
UNION
SELECT t1.Id, t1.Priority, COALESCE(t3.Device, '') AS [Service/Device]
FROM t1
LEFT JOIN t3 ON t1.Id = t3.Id
WHERE t1.Priority != 4
SQL Fiddle example
select T1.id , T1.PRIORITY ,T2.SERVICE as service/Device from t1
left outer join T2 on T2.id=T1.id where T1.PRIORITY!=4
union all
select T1.id , T1.PRIORITY ,T3.DEVICE as service/Device from t1
left outer join T3 on T3.id=T1.id where PRIORITY!=4