trouble with postgresql subquery - sql

Here are my tables:
table1:
ID | data1 | data2
1 | xxx | xxx
2 | xxx | xxx
table2:
ID | table1_id
20 | 1
21 | 1
25 | 2
26 | 2
table3:
ID | table2_id
30 | 20
31 | 21
32 | 25
33 | 26 <--
I have marked the relevant row by an arrow (table3: ID=33 | table2_id=26)
Now, I want the matching ID with data 1 and data 2 from table 1. In this case: 2
I tried something ...
SELECT t1."ID"
FROM table AS t1
INNER JOIN table2 AS tb2
ON t1."ID" = t2."ID"
INNER JOIN table3 AS t3
ON t2."ID" = 26
... but it returns nothing. Have anybody a working subquery for me :)

you join on the wrong fields
SELECT t1."ID"
FROM table AS t1
INNER JOIN table2 AS t2
ON t1."ID" = t2.table1_id
INNER JOIN table3 AS t3
ON t2."ID" = t3.table2_id
WHERE t3."ID" = 33

Related

SQL LEFT JOIN behaviour

Trying to get a SQL LEFT JOIN to return NULLs where there are no corresponding rows in the other table.
Table 1 - T1
id n
1 aaa
2 bbb
3 ccc
Table 2 - T2
t1_id t3_id
1 1
2 1
3 1
1 2
3 2
2 3
3 3
In T2, note that there is no combination of 2 - 2 or 1 - 3.
select *
from t1
left join t2
on t1.id = t2.t1_id
order by t2.t3_id, t1_id
Output:
id n t1_id t3_id
1 aaa 1 1
2 bbb 2 1
3 ccc 3 1
1 aaa 1 2
3 ccc 3 2
2 bbb 2 3
3 ccc 3 3
I was expecting there to be two additional rows
1 aaa null null
2 bbb null null
...corresponding to the previously mentioned missing combinations in T2.
Note the ORDER BY is only there for convenience - it makes no difference to the rows returned.
Please help me understand why this is happening, and how to get around it.
If you want all rows in t2 in the result set, it should be the first table referenced in the left join:
select *
from t2 left join
t1
on t1.id = t2.t1_id
order by t2.t3_id, t2.t1_id;
EDIT:
You seem to want to generate new rows not in the original data. Use cross join to generate the rows and then left join to bring them in:
select t3.t3_id, t1.id, t1.n
from (select distinct t2.t3_id from t2) as t3 cross join
t1 left join
t2
on t3.t3_id = t2.t3_id and t2.t1_id
Alternatively, if you do want to reference t1 first in the FROM, you would use a RIGHT JOIN instead (personally I find these less intuitive but some do prefer them, and they do have their uses when more tables are involved):
SELECT *
FROM t1
RIGHT JOIN t2 ON t1.id = t2.t1_id
ORDER BY t2.t3_id,
t1_id;
table1:
-------------
| id | name |
-------------
| 1 | john |
-------------
| 2 | mark |
-------------
| 3 | will |
-------------
table2:
-----------------
| t1_id | t3_id |
-----------------
| 1 | 3 |
-----------------
| 1 | 2 |
-----------------
| 3 | 1 |
-----------------
if i want to get table1 through table2:
SELECT t1.*
FROM table2 as t2
LEFT JOIN table1 as t1
ON t1.id = t2.t1_id
WHERE 1
ORDER BY t1.id ASC;
you'll get:
-------------
| id | name |
-------------
| 1 | john |
-------------
| 1 | john |
-------------
| 3 | will |
-------------
edited:
so the query will get all what's in table2, so (t1_id: 1, t3_id: 3), (t1_id: 1, t3_id: 2), (t1_id: 3, t3_id: 1), then the left join will compare the id of t1 with t1_id in t2 and return all columns in t1 as i wrote *.

(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

Join three tables with counts

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

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