Join three tables with counts - sql

I have these three tables (Soknad, Prognose and Did) in the SQL Server database:
Table Soknad has columns: S_ID (key), S_REFNR
Table Prognose has columns: P_ID (key), P_S_ID
Table Did has columns: D_ID (key), D_S_ID, Did_Something
Prognose.P_S_ID is foreign key to Soknad.S_ID.
Did.D_S_ID is foreign key to Soknad.S_ID.
The tables are like this:
SOKNAD
S_ID | S_REFNR |
1 | abc |
2 | cbc |
3 | sdf |
PROGNOSE
P_ID | P_S_ID |
10 | 1 |
11 | 2 |
DID
D_ID | D_S_ID | D_Did_Something |
100 | 1 | 1 |
101 | 1 | 1 |
102 | 1 | 0 |
103 | 2 | 1 |
104 | 2 | 1 |
I want to join these tables (like a view or select statement). From the Did table a count of column Did_Something should be returned, as well as a count of the same column where the value is 1 (one).
The result should be:
S_ID | S_REFNR | P_ID | Count_D_Did_Something | Count_D_Did_Something_Is_One |
1 | abc | 10 | 3 | 2 |
2 | cbc | 11 | 2 | 2 |
3 | sdf | | | |
Any help would be appreciated!

I believe what you want to do is join two tables and put the counts where the rows match the left table in separate columns for each table.
This would accomplish that.
select t1.id, count(t2.id) t2_count , count(t3.id) t3_count
from table1 as t1
left outer join table2 as t2 on t2.table1_id = t1.id
left outer join table3 as t3 on t3.table1_id = t1.id
group by t1.id;
To accomplish the counts you want based on criteria from one of the outer joined tables, you can do that this way, using a derived table...
select t1.id, count(t2.id) t2_count, count(tt2.mCount) Did_SomethingCount, count(t3.id) t3_count
from table1 as t1
left outer join table2 as t2 on t2.table1_id = t1.id
left outer join (select count(*), table1_id mCount from table2 where Did_Something = 1 group by table1_id) as tt2 on tt2.table1_id = t1.id
left outer join table3 as t3 on t3.table1_id = t1.id
group by t1.id;

Here you go:
select s.s_id,
p.p_id,
count(d.Did_Something) as Count_D_Did_Something, -- nulls won't be counted
sum(CASE WHEN d.Did_Something = 1 THEN 1 ELSE 0 END) as Count_D_Did_Something_is_one
from Soknad as s
left join Prognose as p on p.P_S_ID = s.s_id
left join Did as d on d.D_S_ID = s.s_id

This should be simply give the results you need. Note, I simply summed up when you want count to be for values having one,
SELECT S.S_ID, S.REFNR, P.P_ID, COUNT(D.D_DID_SOMETHING) AS COUNT_D_DID_SOMETHING,
SUM(D_DID_SOMETHING) AS COUNT_D_DID_SOMETHING_IS_ONE
FROM SOKNAD AS S
INNER JOIN PROGNOSE AS P
ON P.P_S_ID = S.S_ID
INNER JOIN DID AS D
ON D.D_S_ID = S.S_ID
GROUP BY S.S_ID, S.REFNR, P.P_ID

Related

Joining Two Tables, Same ID - Return both IDs even if Null

I have two tables
+-----+----------+
| SKU | Quantity |
+-----+----------+
| ABC | 30 |
| DEF | 40 |
+-----+----------+
+-----+----------+
| SKU | OnOrder |
+-----+----------+
| ABC | 90 |
| XYZ | 80 |
+-----+----------+
I want to join both tables on SKU when there is a match, but also return SKU from both tables when there isn't a match. So the results would be:
+-----+---------+---------+
| SKU | OnOrder | OnOrder |
+-----+---------+---------+
| ABC | 90 | 30 |
| DEF | 40 | |
| XYZ | | 80 |
+-----+---------+---------+
I'm thinking this would be accomplished by using a left join and a right join and by doing a union but I can't seem to get the code right.
Your help is much appreciated!
You can use a full join:
select coalesce(t1.sku, t2.sku), t1.quantity, t2.onorder
from table1 t1 full join
table2 t2
on t1.sku = t2.sku;
If your database doesn't support full join, the best workaround is probably:
select t1.sku, t1.quantity, t2.onorder
from table1 t1 left join
table2 t2
on t1.sku = t2.sku
union all
select t2.sku, null, t2.onorder
from table2
where not exists (select 1 from table1 t1 where t1.sku = t2.sku);
You can first select all the SKU values and then join that to both tables:
with skus(sku) as (
select sku from table1
union
select sku from table2
)
select a.sku, b.quantity, c.onorder
from skus a
left join table1 b on a.sku = b.sku
left join table2 c on a.sku = c.sku;

Join same table with different column

Hi This may be a stupid question but I have a scenario where my columns tl1,tl2 and tl3 refers to column id table structure is below,
id | name | email | tl1 | tl1 | tl3 |
1 | xyz |x#g.com| null| 1 | 2 |
======================================
2 | abc |z#g.com| null| 1 | 3 |
======================================
3 | def |d#g.com| 1 | 2 | 4 |
SO need to write a query to get the name of tl1,tl2 and tl3,
like below
id | name | email | tl1 | tl1 | tl3 |
1 | xyz |x#g.com| null| xyz | abc |
======================================
2 | abc |z#g.com| null| xyz | def|
======================================
3 | def |d#g.com| xyz | abc | ghi |
I am not able to create query for this scenario, I actually created one but not getting unique records
This is the query which I tried
select distinct a.branch_code,a.email,a.partner_name,a.role_assigned,a.category,b.partner_name as tl1,
c.partner_name as tl2,d.partner_name as tl3
from branch_master as a
left join branch_master as b on b.tl1 = a.branch_code
left join branch_master as c on c.tl2 = a.branch_code
left join branch_master as d on d.tl3 = a.branch_code
Any help would be appreciated.
You need to left join the table 3 times with itself:
select
t.id, t.name, t.email,
t1.name name1, t2.name name2, t3.name name3
from tablename t
left join tablename t1 on t1.id = t.tl1
left join tablename t2 on t2.id = t.tl2
left join tablename t2 on t3.id = t.tl3
First, this is generally a bad data format -- typically, you want the values in different tables. There are some cases where it might make sense to have the data across columns -- for instance, if role are different: submitted_by, processed_by, approved_by. But generally, you want a junction/association table.
The solution to your problem, though, is multiple left joins:
select t.*, t1.email as email1, t2.email as email2, t2.email as email3
from t left join
t t1
on t1.tl1 = t.id left join
t t2
on t2.tl2 = t.id left join
t t3
on t3.tl3 = t.id;

(T-SQL) Join two columns to one common column

I have this problem:
TABLE1:
| ID | DESCRIPTION |
| 10 | Apple |
| 20 | Banana |
| 33 | Pineapple |
| 47 | Orange |
TABLE2:
| ID | FRUIT1 | FRUIT2 |
| 1 | 10 | 47 |
| 2 | 47 | 10 |
| 3 | 33 | 20 |
| 4 | 20 | 33 |
If I select all data in TABLE2, I want in output the name of the fruits (TABLE1.DESCRIPTION) for TABLE2.FRUIT1 and TABLE2.FRUIT2 and not the ID.
How can I do it?
Join table2 twice with different alias name
select t2.id, f1.description, f2.description
from table2 t2
left join table1 f1 on f1.id = t2.fruit1
left join table1 f2 on f2.id = t2.fruit2
You can join back to Table1 twice; you just need to give different table aliases:
SELECT ID, T1a.Description [Fruit1], T1b.Description [Fruit2]
FROM Table2 T2
INNER JOIN Table1 T1a
ON T2.Fruit1 = T1a.ID
INNER JOIN Table1 T1b
ON T2.Fruit1 = T1b.ID
Use a union to combine the columns together like this:
Select t1.Description
from Table2 t2
INNER JOIN Table1 t1 on t1.ID = t2.Fruit1
UNION
Select t1.Description
from Table2 t2
INNER JOIN Table1 t1 on t1.ID = t2.Fruit2

Select datas from multiple tables using one common table in sql server 2005

I have many tables and one common table that have ids of all these tables
for eg:
Table1
| ID | VALUE | DATE |
---------------------------
| 1 | 200 | 25/04/2013 |
| 2 | 250 | 26/05/2013 |
Table2
| ID | VALUE | DATE |
---------------------------
| 1 | 300 | 25/05/2013 |
| 2 | 100 | 12/02/2013 |
Table3
| ID | VALUE | DATE |
---------------------------
| 1 | 500 | 5/04/2013 |
| 2 | 100 | 1/01/2013 |
and one common table
| ID | TABLE | TABLEID |
-------------------------
| 1 | table1 | 1 |
| 2 | table3 | 1 |
| 3 | table2 | 1 |
| 4 | table1 | 2 |
| 5 | table2 | 2 |
| 6 | table3 | 2 |
and using this common table i need to select all datas in above 3 tables
eg:
output
id table tableid value date
1 table1 1 200 25/04/2013
2 table3 1 500 5/04/2013
3 table2 1 300 25/05/2013
4 table1 2 250 26/05/2013
5 table2 2 100 12/02/2013
6 table3 2 100 1/01/2013
If you don't want to use UNION ALL you can use COALESCE for the same using LEFT JOIN like this:
SELECT c.*
, COALESCE(t1.Value, t2.Value,t3.Value) AS Value
, COALESCE(t1.Date, t2.Date,t3.Date) AS Date
FROM Common c
LEFT JOIN Table1 t1 ON c.tableid = t1.[id]
AND [Table] = 'table1'
LEFT JOIN Table2 t2 ON c.tableid = t2.[id]
AND [Table] = 'table2'
LEFT JOIN Table2 t3 ON c.tableid = t3.[id]
AND [Table] = 'table3'
ORDER BY ID;
See this SQLFiddle
By this way you can reduce your task to join all records using UNION ALL. But for the given data structure you have to join all tables anyhow.
You need to join all tables with common table separately then join them using UNION ALL:
SELECT *
FROM Common c
JOIN Table1 t1 ON c.tableid = t1.[id]
AND [Table] = 'table1'
UNION ALL
SELECT *
FROM Common c
JOIN Table2 t2 ON c.tableid = t2.[id]
AND [Table] = 'table2'
UNION ALL
SELECT *
FROM Common c
JOIN Table3 t3 ON c.tableid = t3.[id]
AND [Table] = 'table3';
See this SQLFiddle
You can UNION ALL the tables adding flag column in the process and then JOIN the result with common table.
WITH CTE_Tables AS
(
SELECT 'Table1' AS Tab, * FROM Table1
UNION ALL
SELECT 'Table2' AS Tab, * FROM Table2
UNION ALL
SELECT 'Table3' AS Tab, * FROM Table3
)
SELECT *
FROM CommonTable c1
LEFT JOIN CTE_Tables cte ON cte.ID = c1.TableID AND cte.Tab = c1.[Table]
SQLFiddle DEMO

MySQL get data from another table with duplicate ID/data

How to query data from table_1 which ID is not available on table_2 that has duplicate ID's. See example below.
I want to get ID 5 and 6 of Table 1 from Table 2
Table 1
-------------
| ID | Name |
| 1 | a |
| 2 | b |
| 3 | c |
| 4 | d |
| 5 | e |
| 6 | f |
-------------
Table 2
-------------
Table 1 ID |
| 1 |
| 1 |
| 2 |
| 2 |
| 2 |
| 3 |
| 4 |
-------------
Thanks!
Minus query would be very helpful, see this link: minus query replacement
for your data this would look like this:
SELECT table_1.id FROM table_1 LEFT JOIN table_2 ON table_2.id = table_1.id WHERE table_2.id IS NULL
Use:
SELECT t.id
FROM TABLE_1 t1
LEFT JOIN TABLE_2 t2 ON t2.id = t1.id
WHERE t2.id IS NULL
Using NOT EXISTS:
SELECT t.id
FROM TABLE_1 t1
WHERE NOT EXISTS(SELECT NULL
FROM TABLE_2 t2
WHERE t2.id = t1.id)
Using NOT IN:
SELECT t.id
FROM TABLE_1 t1
WHERE t1.id NOT IN (SELECT t2.id
FROM TABLE_2 t2)
Because there shouldn't be NULL values in table2's id column, the LEFT JOIN/IS NULL is the fastest means: http://explainextended.com/2009/09/18/not-in-vs-not-exists-vs-left-join-is-null-mysql/
If I am understanding you correctly you want to do an outer join. In this case it would be:
SELECT * FROM
table_1 LEFT JOIN ON table_2
ON table_1.id = table_2.id
WHERE table_2.id is NULL
This one does what you want:
Select t1.id
From table1 t1
Left Join table2 t2
On t2.id = t1.id
Where t2.id Is Null
Result:
id
--
5
6