fetch the unique data from two tables - mysql

I have two tables. ProductA and ProductB.
ProductA
+----+-------+
| ID | SubId |
+----+-------+
| A1 | 112 |
| B1 | 111 |
| C1 | 115 |
| D1 | 117 |
| E1 | 114 |
| F1 | 112 |
+----+-------+
ProductB
+----+-------+
| ID | SubId |
+----+-------+
| A1 | 112 |
| B1 | 111 |
| C1 | 115 |
| G1 | 001 |
| H1 | 002 |
| k1 | 003 |
+----+-------+
I want to write a query which retrieves two columns ID and SubId and displays distinct rows from ProductA table which are NOT IN ProductB. So for the above tables.
Expected Result
+----+-------+
| ID | SubId |
+----+-------+
| D1 | 117 |
| E1 | 114 |
| F1 | 112 |
+----+-------+
How can I get this done?

Query
select distinct *
from productA
where not exists
(
select null
from productB
where productA.id = productB.id
and productA.subid=productB.subid
);
Fiddle demo here

Try this query
select * from ProductA where not EXISTS(select * from productb)

SELECT <select_list>
FROM TableA A
FULL OUTER JOIN TableB B
ON A.Key==B.Key
WHERE A.Key is NULL OR B.Key IS NULL;

select * from productA a
left outer join productB b
on a.ID = b.ID
and a.subid=b.subid
where b.subid is null
and b.id is null;

Update
24 revisions later! How do you like me NOW!
http://sqlfiddle.com/#!9/954792/24
SELECT
foo.pid,
foo.sid from (
SELECT
PA.`ID` as pid,
PA.`SubId` as sid
FROM
`ProductA` as PA
LEFT JOIN
`ProductB` as PB
ON
PA.`ID` = PB.`ID`
WHERE
PB.`ID` is NULL
UNION
SELECT
P2A.`ID` as ppid,
P2A.`SubId` as ssid
FROM
`ProductA` as P2A
RIGHT JOIN
`ProductB` as P2B
ON
P2A.`ID` = P2B.`ID`
WHERE
P2B.`ID` is NULL
) as foo
Here is a good link that explains joins...
http://blog.codinghorror.com/a-visual-explanation-of-sql-joins/

You should try following,
Select * from ProductA A
Left Join ProductB B on A.ID = B.Id
Where B.Id is null or B.SubId is null
it will give you desire result.

Related

MySQL JOIN two tables on closest matching value

I have the following situation:
tableA
+-------+-------+
| id | Value |
+-------+-------+
| 1 | 1000 |
| 2 | 20 |
| 3 | 62 |
| 4 | 0 |
+-------+-------+
tableB
+-------+--------+
| Value | Lookup |
+-------+--------+
| 10 | a |
| 20 | b |
| 30 | b |
| 40 | g |
| 50 | h |
| 60 | f |
| 70 | a |
| 80 | a |
| 90 | v |
| 100 | b |
+-------+--------+
And I need to return the lookup in table B that most closely matches the value field in table A. For example.
+-------+-------+--------+
| id | Value | Lookup |
+-------+-------+--------+
| 1 | 1000 | b |
| 2 | 20 | b |
| 3 | 62 | f |
| 4 | 0 | a |
+-------+-------+--------+
How can I go about doing this?
Here is an option using joins:
SELECT
a.Id, a.Value, b.Lookup
FROM tableA a
CROSS JOIN tableB b
INNER JOIN
(
SELECT a.Id, MIN(ABS(a.Value - b.Value)) AS min_abs_value
FROM tableA a
CROSS JOIN tableB b
GROUP BY a.Id
) t
ON a.Id = t.Id AND
ABS(a.Value - b.Value) = t.min_abs_value;
Demo
While this query does join to a subquery, the subquery is not correlated.
One way is to use a correlated subquery:
SELECT a.Id, a.Value,
(SELECT b.Lookup
FROM TableB AS b
ORDER BY ABS(a.Value - b.Value) LIMIT 1)
FROM TableA AS a
Demo here

SQL - How can I JOIN two tables and SUM a column based on IDs between them?

I have two tables. One table is with master data
Table tbl1:
+-------------+------------+------------+
| ID | Name | Total |
+-------------+------------+------------+
| 1 | a | 10 |
| 2 | b | 5 |
| 3 | c | 4 |
| 4 | a | 4 |
+-------------+------------+------------+
Second table tbl2 contains child data. The key between tables is ID
Table tbl2:
+-------------+------------+
|id | qty |
+-------------+------------+
| 1 | 4 |
| 1 | 3 |
| 1 | 1 |
| 3 | 1 |
| 3 | 3 |
+-------------+------------+
I need to get output like this:
Output:
+-------------+------------+------------+
| name | sum_tot | sum_qty |
+-------------+------------+------------+
| a | 14 | 8 |
| b | 5 | 0 |
| c | 4 | 4 |
+-------------+------------+------------+
I had tried with this:
select tbl1.name, SUM(tbl1.total), SUM(tbl2.qty)
from tbl1
left join tbl2 ON tbl1.id = tbl2.id
GROUP by tbl1.name
The output that I get is:
Output:
+-------------+------------+------------+
| name | sum_tot | sum_qty |
+-------------+------------+------------+
| a | 34 | 8 |
| b | 5 |null |
| c | 8 | 4 |
+-------------+------------+------------+
Which is not correct.
Here is the sql fiddle:
The summary from first table is not in relation with second table. It seems that somehow query runs three times.
You can simply have a correlated sub-query that calculates the tbl2 sum:
select tbl1.name,
SUM(tbl1.total),
SUM(COALESCE((select SUM(tbl2.qty)
from tbl2
where tbl1.id = tbl2.id), 0)) as qty_tot
from tbl1
GROUP by tbl1.name
SELECT A.name, SUM(A.total) as sum_tot, COALESCE(B.sum_qty, 0) as sum_qty
FROM tbl1 A
LEFT JOIN (
SELECT id, SUM(qty) as sum_qty
FROM tbl2
GROUP BY id
) B ON B.id = A.id
GROUP BY A.name
select tbl1.name, SUM(tbl1.total), SUM(COALESCE(tbl2.qty, 0))
from tbl1
left join tbl2 ON tbl1.id = tbl2.id
GROUP by tbl1.name

SQL join table with same column name

I want to join two tables with the same column names and update it using by ID (unique key)
With your Example:
select * from Table1;
+----+------+------+--------+
| ID | Name | age | Gender |
+----+------+------+--------+
| 1 | Pars | 23 | M |
| 2 | Pepe | 24 | M |
| 3 | Pio | 25 | M |
| 4 | Pak | 26 | F |
+----+------+------+--------+
select * from Table2;
+------+------+------+--------+
| ID | Name | age | Gender |
+------+------+------+--------+
| 1 | Pars | 30 | M |
| 2 | Pepe | 31 | M |
| 3 | Pio | 32 | M |
+------+------+------+--------+
After the Update Query:
Update Table1 join Table2 using(ID) set Table1.AGE=Table2.AGE;
RESULT:
select * from Table1;
+----+------+------+--------+
| ID | Name | age | Gender |
+----+------+------+--------+
| 1 | Pars | 30 | M |
| 2 | Pepe | 31 | M |
| 3 | Pio | 32 | M |
| 4 | Pak | 26 | F |
+----+------+------+--------+
I think that this may help you.....
The query uses the inner join to join the table1 and table2
SELECT T1.name1,T2.name2
FROM `table1` T1
INNER JOIN `table2` T2 ON t2.name1=t1.PrimaryKey;
Used left join to join the tables.
Try this code:-
select a.id ,
coalesce(a.name,b.name) as name
,coalesce(b.age,a.age)as age
,coalesce(a.gender,a.gender)as gender
from table1 as a
left join Table2 as b
on a.id=b.id
Try this also:
update Table1 set Table1.age=Table2.age from table1 inner join table2 on Table1.id=Table2.id

MySQL joins and group columns

In the following situation i need to somehow group some columns into one. I have the following query:
SELECT a.id,b.id,c.id,d.id
FROM some_table AS a
LEFT JOIN some_table AS b ON ( a.id=b.parent_id )
LEFT JOIN some_table AS c ON ( b.id=c.parent_id )
LEFT JOIN some_table AS d ON ( c.id=d.parent_id )
WHERE a.id = '22'
Results in:
+--------+--------+--------+--------+
| a.id | b.id | c.id | d.id |
+--------+--------+--------+--------+
| 22 | 24 | 25 | null |
| 22 | 381 | null | null |
| 22 | 418 | 2389 | 9841 |
+--------+--------+--------+--------+
This is an category table populated with 220,000+ rows.
I need the last id (which is not NULL). So in this case i need (25,381,9841)
What is the easiest way to achieve this?
best result should be:
+------+
| id |
+------+
| 25 |
| 381 |
| 9841 |
See COALESCE(). That's all you need!
To expand on the above answer, it seems like you need
SELECT a.id, COALESCE(d.id, c.id, b.id) AS 'id'
FROM some_table AS a
LEFT JOIN some_table AS b ON ( a.id=b.parent_id )
LEFT JOIN some_table AS c ON ( b.id=c.parent_id )
LEFT JOIN some_table AS d ON ( c.id=d.parent_id )
WHERE a.id = '22'
That would give you an output of
+------+------+
| a.id | id |
+------+------+
| 22 | 25 |
| 22 | 381 |
| 22 | 9841 |

MySQL UNION with WHERE

I have the following 2 tables
tableA a (id, name, surname, program, date)
tableB b (id, aid, name, surname, extracard)
with tableA.id = tableB.aid (1 to n relationship)
Sample data for tableA:
| ID | NAME | SURNAME | PROGRAM | DATE | EXPIRES |
----------------------------------------------------------
| 1 | TOM | JONES | 1,2,3 | 12/8/2012 | 12/8/2013 |
| 2 | JAMIE | OLIVER | 4,5,6 | 15/8/2012 | 15/8/2013 |
Sample data for tableB:
| ID | AID | NAME | SURNAME | CARD |
-------------------------------------
| 1 | 1 | ANNE | JONES | 1 |
| 2 | 1 | JACK | BOWER | 0 |
| 3 | 2 | KATE | PERRY | 1 |
| 4 | 2 | JOHN | DOE | 0 |
| 5 | 2 | HARRY | POTTER | 0 |
In the results, each member of tableB should have all values (program, date, expires, etc...) from tableA and display only the name, surname from tableB in the same column (coalesce??). Also, I need to use a between clause for a.id between (%id1 and %id2) and also a WHERE statement for selecting rows where tableB.card=1
| a.ID | NAME | SURNAME | PROGRAM | DATE | EXPIRES |
------------------------------------------------------------
| 1 | TOM | JONES | 1,2,3 | 12/8/2012 | 12/8/2013 |
| 1 | ANNE | JONES | 1,2,3 | 12/8/2012 | 12/8/2013 |
| 2 | JAMIE | OLIVER | 4,5,6 | 15/8/2012 | 15/8/2013 |
| 2 | KATE | PERRY | 4,5,6 | 15/8/2012 | 15/8/2013 |
SELECT * FROM
( (SELECT a.id ,a.name,a.surname,a.program,a.date,a.expires
from tableA a left outer join tableB b
on b.aid=a.id
where b.card=1 and (a.id between '1' and '2'))
UNION ALL
(SELECT a.id ,b.name,b.surname,a.program,a.date,a.expires
from tableA a left outer join tableB b
on b.aid=a.id
where b.card=1 and (a.id between '1' and '2'))) t
ORDER BY id
EDITED:
Please refer to http://sqlfiddle.com/#!2/d8227/1
Are you looking for -
(SELECT a.id, name, surname, program, date, expires FROM tableA a WHERE a.id BETWEEN '%id1' and '%id2')
UNION
(SELECT a.id, b.name, b.surname, program, date, expires FROM tableB b LEFT JOIN tableA a ON b.aid=a.id WHERE b.card=1 AND (a.id between '%id1' and '%id2') )
ORDER BY a.id ASC
(select a.ID,a.NAME,a.SURNAME,a.PROGRAM,a.DATE,a.EXPIRES from tableA a where ...)
Union All
(select a2.ID,b.NAME,b.SURNAME,a2.PROGRAM,a2.DATE,a2.EXPIRES from tableB b
left join tableA a2 on b.aid = a2.id where ...);
You can choose left/inner join as per your need and where condition too with between clause like.. where id between 2 and 8 or where id > 2 and id < 8.