pulling data from two different tables with common row elements - mysql

I have the following two tables:
Table a:
name qty
a 10
b 20
c 30
d 40
and table b
name qty
a 10
b 20
d 20
e 60.
I want to merge there two tables and create a new table like this
name qty
a 20
b 40
c 30
d 60
e 60
The objective is to add the values if there is have the same value in name or else just append the values in table two to table 1.

Unfortunately, MySQL does not support full outer join. Here is a method using union all and group by:
select name, sum(qty) as qty
from ((select name, qty from a) union all
(select name, qty from b)
) ab
group by name;

To simulate a full outer join, just execute a left outer join (gives all the rows of Table A with all matching rows of Table B or NULL) and a right outer join where Table A is NULL (gives all the rows of Table B that have no match in Table A -- matches are already provided in first query).
In the first query, there will always be a Qty value from Table A with either a Qty value or NULL from Table B. In the second query, there will only be a Qty value from Table B.
See Fiddle results.
select a.Name, a.Qty + IsNull( b.Qty, 0 ) as Qty
from #TableA a
left outer join #TableB b
on b.Name = a.Name
union all
select b.Name, b.Qty
from #TableA a
right outer join #TableB b
on b.Name = a.Name
where a.Name is null;
You may use union or union all with the same results. Since there is less processing required with union all, that's what I chose.

Related

Left join in SQL to identify certain rows

Given below is table A:
Cust_id
Code
1
101
1
102
1
103
2
201
Table B:
Cust_id
Code
1
101
1
102
Table B has only customer 1 and contains only two product codes of customer 1.
I want to identify the code of customers in Table B that is not present in Table B.
Cust_id
Code
1
103
To get this, I did Table A left join Table B on cust_id and code and thought those with null values of code in Table B would give the desired result, but it did not seem to work. It would be really helpful if someone could tell what should the correct steps be. Thanks
My query so far:
select a.cust_id, a.code, b.cust_id as customer, b.code as product
from a
left join b on a.cust_id = b.cust_id and a.code = b.code
Two conditions:
cust_id must be in table B
(cust_id, code) must not be in table B
The query with the conditions almost literally translated from human language to SQL:
select *
from a
where cust_id in (select cust_id from b)
and (cust_id, code) not in (select cust_id, code from b);
List item
Hello other solution using exists
select a.cust_id, a.code
from TABLEA a left join TABLEB b on
a.cust_id=b.cust_id and a.code=b.code
where b.cust_id is null and exists( select * from TABLEB
where cust_id=a.cust_id)

SQL Query to compare two tables for names

I am building a SQL query which compares two tables A and B by a [name] column and returns the names from table A that are not in table B
Example
Table A
ID Name Address
1 A ABC
2 B XYZ
3 C PQR
Table B
ID Name Gender
1 A F
2 B M
3 D F
The query I wrote should return third row from table A as it is not in table B and should exclude all other rows
Following is the query I built
Select * from A oa left join B gp ON oa.name!=gp.name
the above doesn't return the results I was expecting.
Can this be corrected?
Easiest way:
select * from A where name not in (select name from B)
Better way:
select * from A where not exists (select 1 from B where B.name = A.name)
"A left join B" means keeping everything in A, and associating records in B if the condition is satisfied.
In your case, if you really wanna use left join, here is what it should be ('=', not '!='):
Select * from A oa left join B gp ON oa.name=gp.name where gp.name is null
Better way would be using 'not exists' performance-wise, or 'except' if null values are not an issue.
Using excpet operator will help
select * from TableA
except
select * from TableB
SELECT a.*
FROM A a
LEFT JOIN B b
ON a.name = b.name
WHERE b.name IS NULL

mysql union of 2 tables

I have 2 tables:
table A (id, user_id, flag)
table B (id, user_id, flag)
Here If I take Count of table A it comes as 10 and that of B 5
So Total = 10 + 5 = 15.
SELECT * FROM table A
LEFT JOIN table B ON table B.user_id = table A.user_id
UNION ALL
SELECT * FROM table A
RIGHT JOIN table B ON table B.user_id = table A.user_id
So It should Come 15 instead it showing 50.
use
SELECT * FROM TABLE1 UNION
SELECT * FROM TABLE2
UNION removes duplicate records in other hand UNION ALL does not.Check HERE
You need to make sure the data in your tables are correct.
Table A Should have 15 rows
SELECT COUNT(*) as 'rowCountTableA' FROM table_a;
Table B Should have 5 rows
SELECT COUNT(*) as 'rowCountTableB' FROM table_b;
If your tables are correct and have exactly matching column names you can join them together by specifying asterisks to get all column values.
If however the columns in your table have a few different column names that are in table_a that are not in table_b you must call out the column names instead of using asterisk to get all values.
EXAMPLE:
SELECT (id,user_id,flag) FROM table_a
UNION ALL
SELECT (id,user_id,flag) FROM table_b

Select Matched Pairs from Two Tables

I need to select matched pairs from two tables containing similarly structured data. "Matched Pair" here means two rows that reference each other in the 'match' column.
A single-table matched pair example:
TABLE
----
id | matchid
1 | 2
2 | 1
ID 1 and 2 are a matched pair because each has a match entry for the other.
Now the real question: what is the best (fastest) way to select the matched pairs that appear in both tables:
Table ONE (id, matchid)
Table TWO (id, matchid)
Example data:
ONE TWO
---- ----
id | matchid id | matchid
1 | 2 2 | 3
2 | 3 3 | 2
3 | 2
4 | 5
5 | 4
The desired result is a single row with IDs 2 and 3.
RESULT
----
id | id
2 | 3
This is because 2 & 3 are a matched pair in table ONE and in table TWO. 4 & 5 are a matched pair in table ONE but not TWO, so we don't select them. 1 and 2 are not a match pair at all since 2 does not have a matching entry for 1.
I can get the matched pairs from one table with this:
SELECT a.id, b.id
FROM ONE a JOIN ONE b
ON a.id = b.matchid AND a.matchid = b.id
WHERE a.id < b.id
How should I build a query that selects only the matching pairs that appear in both tables?
Should I:
Select the query above for each table and WHERE EXISTS them together?
Select the query above for each table and JOIN them together?
Select the query above then JOIN table TWO twice, once for 'id' and once for 'matchid'?
Select the query above for each table and loop through to compare them back in php?
Somehow filter table TWO down so we only have to look at the IDs in matched pairs in table ONE?
Do something totally different?
(Since this is a question of efficiency, it is worth noting that the matches will be quite sparse, maybe 1/1000 or less, and each table will have 100,000+ rows.)
I think I get your point. You want to filter the records in which the pairs exists on both tables.
SELECT LEAST(a.ID, a.MatchID) ID, GREATEST(a.ID, a.MatchID) MatchID
FROM One a
INNER JOIN Two b
ON a.ID = b.ID AND
a.matchID = b.matchID
GROUP BY LEAST(a.ID, a.MatchID), GREATEST(a.ID, a.MatchID)
HAVING COUNT(*) > 1
SQLFiddle Demo
Try this Query:
select
O.id,
O.matchid
from
ONE O
where
(CAST(O.id as CHAR(50))+'~'+CAST(O.matchid as CHAR(50)))
in (select CAST(T.id as CHAR(50))+'~'+CAST(T.matchid as CHAR(50)) from TWO T)
Edited Query:
select distinct
Least(O.id,O.matchid) ID,
Greatest(O.id,O.matchid) MatchID
from
ONE O
where
(CAST(O.id as CHAR(50))+'~'+CAST(O.matchid as CHAR(50)))
in (select CAST(T.id as CHAR(50))+'~'+CAST(T.matchid as CHAR(50)) from TWO T)
and (CAST(O.matchid as CHAR(50))+'~'+CAST(O.id as CHAR(50)))
in (select CAST(T.id as CHAR(50))+'~'+CAST(T.matchid as CHAR(50)) from TWO T)
SQL Fiddle
Naive version, which checks all the four rows that need to exist:
-- EXPLAIN ANALYZE
WITH both_one AS (
SELECT o.id, o.matchid
FROM one o
WHERE o.id < o.matchid
AND EXISTS ( SELECT * FROM one x WHERE x.id = o.matchid AND x.matchid = o.id)
)
, both_two AS (
SELECT t.id, t.matchid
FROM two t
WHERE t.id < t.matchid
AND EXISTS ( SELECT * FROM two x WHERE x.id = t.matchid AND x.matchid = t.id)
)
SELECT *
FROM both_one oo
WHERE EXISTS (
SELECT *
FROM both_two tt
WHERE tt.id = oo.id AND tt.matchid = oo.matchid
);
This one is simpler :
-- EXPLAIN ANALYZE
WITH pair AS (
SELECT o.id, o.matchid
FROM one o
WHERE EXISTS ( SELECT * FROM two x WHERE x.id = o.id AND x.matchid = o.matchid)
)
SELECT *
FROM pair pp
WHERE EXISTS (
SELECT *
FROM pair xx
WHERE xx.id = pp.matchid AND xx.matchid = pp.id
)
AND pp.id < pp.matchid
;

mysql left join returns unexpected amount of rows

I have 2 tables where
tableA has 41 rows
and
tableB has 3 rows
I am trying to get the total rows of these 2 tables via a query using left join but i get way more rows(123) than expected(44)
query:
SELECT COUNT(*)
FROM tableA as u
LEFT JOIN tableB as d
ON u.uid=d.uid
WHERE
u.uid=912391178669
AND
u.deleted = 0
AND
d.deleted=0
tables schema:
tableA
id | uid | deleted
tableB
id | uid | deleted
I have run the following query It is working correctly.. U can check it out.
SELECT
( SELECT count(*) from table1 where.... )
+ ( SELECT count(*) from table2 where.... )
as total from dual
I'm guessing that you have three rows in tableA with the uid given in the query. That will mean that each row in tableA will join once with each row in tableB, which means you will back 41 x 3 rows or 123.
From the number of rows you are expecting back, I wonder if you need a Union instead of a join.
Select * from tableA where uid = 912391178669 and deleted = 0
union all
Select * from tableB where uid = 912391178669 and deleted = 0
A union will combine the results of two queries. A join will combine the columns of table tables in a single query.
41*3=123
each row of TableA has uid=912391178669 and tableB each row also have uid that's why you are getting 123 row total. use some filter criteria to get desired result (like some AND condition)
if you can show us your table column then it may be possible to help you .
Left join does not combine the rows of two table .
TableA left join TableB will give you all the row of table A meeting the joining condition.
SELECT COUNT(*)
FROM tableA as u
LEFT JOIN tableB as d
ON u.uid=d.uid
AND
u.deleted = d.deleted
WHERE
u.uid=912391178669
AND u.deleted = 0
SELECT SUM(
(SELECT count(*) from tableA WHERE uid=912391178669)
+ (SELECT count(*) from tableA WHERE uid=912391178669)
) as totalRows