MySQL get data from another table with duplicate ID/data - sql

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

Related

How to find rows that have only one value in another table

I want to find rows from table 1 that are joining with table 2 and have all rows same in table 2.
Example:
Row with id 4 in table2 is not valid because have different values in table1 (value1, value)
Row with id 5 in table2 is valid because have same values in table1 (value3)
table1
+----+--------+----------+
| id |table2Id| value |
+----+--------+----------+
| 1 | 4 |value1 |
| 2 | 4 |value2 |
| 3 | 5 |value3 |
| 4 | 5 |value3 |
| 5 | 5 |value3 |
+----+--------+----------+
table2
+----+
| id |
+----+
| 4 |
| 5 |
+----+
I'm not sure why a join is necessary. You can just use the information in table1:
select t1.*
from (select t1.*,
min(value) over (partition by table2id) as min_value,
max(value) over (partition by table2id) as max_value
from table1 t1
) t1
where min_value = max_value;
Or use not exists:
select t1.*
from table1 t1
where not exists (select 1
from table1 tt1
where tt1.table2id = t1.table2id and
tt1.value = t1.value
);
In either case, you can join to table2 if you need to for filtering or for other columns, but based on the information in your question the join is not needed.
You can do the following:
SELECT * FROM (
SELECT max(table2Id) as Id,value
FROM table1
GROUP BY value
HAVING COUNT(value)=1) JOIN table2 on table1.Id = table2.Id
Thanks
Try this -
Select t1.* from table1 t1 JOIN table2 t2 on t1.id = t2.id and t1.table2Id = t2.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

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

Working with 2 different tables and getting the latest/most recent values values

Been struggling in Microsoft SQL a couple of hours with this.
I have 2 Tables.
Table1
ID | STOCK | STATUS
-----------------------------
1 | 1 | Out
2 | 1 | In
3 | 1 | Out
4 | 2 | Out
5 | 2 | In
Table2
ID | DATE
---------------
1 | 2013-07-01
2 | 2013-07-02
3 | 2013-07-03
4 | 2013-07-01
5 | 2013-07-02
I want to get the latest STOCK with the latest DATE and STATUS
-> Result must be
Result Table
ID| STOCK | STATUS | DATE
-------------------------------
3 | 1 | Out | 2013-07-03
5 | 2 | In | 2013-07-02
I have done the following:
SELECT Table1.*, Table2.* FROM Table1, Table2 WHERE Table1.ID=Table2.ID
This joins the table but gives all 5 records. So I thought I would use the MAX() function like so
SELECT Table1.*, MAX(Table2.ID),Table2.Date FROM Table1, Table2 WHERE Table1.ID=Table2.ID GROUP BY Table2.Date
But this does not run in the query windows.
SELECT t1.id, t1.stock, t1.status, t5.mdate
FROM Table1 t1
inner join Table2 t2 on t1.id = t2.id
inner join
(
select t3.stock, max(t4.date) as mdate
from table1 t3
inner join Table2 t4 on t3.ID = t4.ID
group by t3.stock
) t5 on t5.stock = t1.stock and t5.mdate = t2.date
SQLFiddle demo
Use this:
Select t1.id,t1.stock,t1.status,t2.date
FROM Table1 as t1,Table2 as t2
Where t1.id=t2.id
Order By t2.date DESC
LIMIT 1