How to merge two tables on ID - mysql

I have two tables, who have the exact same columns. I want to merge table b into table a and if the dataset has the same ID, I want to use the dataset of table b.
I tried something like:
SELECT *
FROM
((SELECT
*
FROM
tableA) UNION (SELECT
*
FROM
tableB)) AS temp
GROUP BY temp.ID
ORDER BY temp.ID
but that gave me a mix of both tables.

You can do this using union all along with some additional logic:
select b.*
from b
union all
select a.*
from a
where not exists (select 1 from b where b.id = a.id);

Related

How to filter out duplicates from a union query?

I have two similar SELECT queries that retrieve data from the same table "my_table".
-- 1st select
SELECT
my_table.id,
a,
b
FROM my_table
JOIN table2 ON u = v
JOIN table3 ON x = y
UNION ALL
-- 2st select
SELECT
my_table.id,
a,
b
FROM my_table
JOIN table2 ON r = s
JOIN table3 ON t = u
Duplicates are to be filtered out under the following conditions:
If the second select returns an id that is already present in the 1st select, it should be discarded.
Is there an easy solution without using a common table expression?
Note: The SQL does not have to be a UNION and can also be changed.
UNION filters out duplicate rows by default. UNION ALL does not remove duplicates.
But the duplicates are based on all columns being identical, not just the id column. If a given id value occurs in both queries, but any of the other two columns are different, then it counts as a distinct row.
If you want to reduce the result to a single row per id, the use a GROUP BY:
SELECT id, ...aggregate expressions...
FROM (
SELECT my_table.id, a, b ...
UNION
SELECT my_table.id, a, b ...
) AS t
GROUP BY id;
When you GROUP BY id, then any other expressions of the outer select-list must be in aggregate functions like MAX() or SUM(), etc.
The reason it is important to use an aggregate function is that when there are multiple rows with the same id value which you want to reduce to one row, what value should be displayed for a and b?
Example:
id
a
b
4
12
24
4
18
28
If you group by id, you would get one row for id=4, but what value for the other two columns?
id
a
b
4
?
?
Read https://dev.mysql.com/doc/refman/8.0/en/group-by-handling.html for more details on this. Or my answer to Reason for Column is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause
You must use an aggregate function, which includes GROUP_CONCAT() to append all the values from that column in a comma-separated list. Or you can use ANY_VALUE() which picks one of the values from that column arbitrarily.
I think this should do it:
-- 1st select
SELECT
my_table.id,
a,
b
FROM my_table
JOIN table2 ON u = v
JOIN table3 ON x = y
WHERE id NOT IN (
SELECT
my_table.id,
FROM my_table
JOIN table2 ON r = s
JOIN table3 ON t = u
)
UNION ALL
-- 2st select
SELECT
my_table.id,
a,
b
FROM my_table
JOIN table2 ON r = s
JOIN table3 ON t = u

Sql query to Select one result per all matches

I got two tables
Table 1:
id|value
1|Tom
1|Lucy
2|Tom
2|Lucy
3|Tom
3|Lucy
3|Bard
Table 2:
id|value
1|Tom
1|Lucy
2|Tom
2|wrong
3|Tom
3|Lucy
Results should be id where all the values match in both tables:
1
Tried this:
select distinct a.id
from table1 a
join table2 b on a.id=b.id and a.value=b.value
results are
1
2
3
INTERSECT comes to mind. Or a FULL OUTER JOIN maybe. MySQL supports neither.
The easiest way I can think of in MySQL:
select id
from table1
group by id
having (id, group_concat(value order by value)) in
(
select id, group_concat(value order by value)
from table2
group by id
);
Demo: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=768cc8fb2d01c2b5219a4d56d127d117

How to optimize sql select statement?

I am having an issue with SQL select statement. I am trying to get the percentage using below logic.
For example, I have two tables. One is TableA and another TableB
TableA has column ID, A1, A2.., Get total distinct count of A1 as "X".
TableB has column ID, B1, B2, FK_A1. Get count of B2 as "Y".
Get (Y/X)*100 as Total Percentage.
I was able to do it using subqueries but would like to use a simple and effective statement. Is it possible to get all the above 3 cases in one select statement? Your help would be highly appreciated.
Select
(Select count(distinct A1) from TableA) As C1,
(Select count(B2) from TableB Inner Join TableA ON TableB.FK_A1=TableA.A1)
C2)
Try this query
SELECT ( COUNT(B2) / COUNT(DISTINCT A1) ) * 100 AS TOTAL_PERC FROM TABLEA A INNER JOIN TABLEB B ON TABLEB.FK_A1 = TABLEA.A1;
You can use a simple join between two tables:
SELECT
( COUNT(DISTINCT A1) / COUNT(B2) ) * 100 AS PRCNTG
FROM
TABLEA A
INNER JOIN TABLEB B ON TABLEB.FK_A1 = TABLEA.A1;
apply DISTINCT on B2 if needed in your case.
apply OUTER join if needed in your case.
Cheers!!
You can use inner join with group by to achieve this. You can also use cte to make your distinct records separately.
; with cte as (
select A1, Count(distinct A1) as CountA from tableA)
, ct as (
select distinct FK_A1 , count(b2) as Count from tableB)
select 100 * ct.count/cte.CountA as totalpercentage
from cte
inner join ct
on cte.A1=ct.FK_A1

SELECT only one entry of multiple occurrences

Let's say I have a Table that looks like this:
id fk value
------------
1 1 'lorem'
2 1 'ipsum'
3 1 'dolor'
4 2 'sit'
5 2 'amet'
6 3 'consetetur'
7 3 'sadipscing'
Each fk can appear multiple times, and for each fk I want to select the last row (or more precise the row with the respectively highest id) – like this:
id fk value
------------
3 1 'dolor'
5 2 'amet'
7 3 'sadipscing'
I thought I could use the keyword DISTINCT here like this:
SELECT DISTINCT id, fk, value
FROM table
but I am not sure on which row DISTINCT will return and it must be the last one.
Is there anything like (pseudo)
SELECT id, fk, value
FROM table
WHERE MAX(id)
FOREACH DISTINCT(fk)
I hope I am making any sense here :)
thank you for your time
SELECT *
FROM table
WHERE id IN (SELECT MAX(id) FROM table GROUP BY fk)
Try this:
SELECT a.id, a.fk, a.value
FROM tableA a
INNER JOIN (SELECT MAX(a.id) id, a.fk FROM tableA a GROUP BY a.fk
) AS b ON a.fk = b.fk AND a.id = b.id;
OR
SELECT a.id, a.fk, a.value
FROM (SELECT a.id, a.fk, a.value FROM tableA a ORDER BY a.fk, a.id DESC) AS a
GROUP BY a.fk;
Try this:
SELECT t.* FROM
table1 t
JOIN (
SELECT MAX(id) as id
FROM table1
GROUP BY fk
) t1
ON t.id = t1.id
Inner query will give you highest id for each fk using MAX(). Then we join this inner table with your main table.
You could also do
SELECT id, fk, value FROM table GROUP BY fk HAVING id = MAX(id)
I don't have mysql here, but it works in Sybase ASE

Can the following be achieved using MYSQL union?

We have a Web Analytics database with 2 tables Table 1 and Table 2 as seen below.
We really could do with some inputs here to display the desired result as a single row.
Many Thanks
X
SELECT
A.Name,
A.ref_num Policy_number,
B.QNum Quote_number
FROM
(
SELECT AA.Name,BB.ref_num FROM
(SELECT Name,ref_num FROM Table1 WHERE Name='Purchase' AND Cookieid=123456) AA
INNER JOIN Table2 BB USING (Reference)
) A,
(
SELECT BB.ref_num QNum FROM
(SELECT * FROM Table1 WHERE Name='Quote' AND Cookieid=123456) AA
INNER JOIN Table2 BB USING (Reference)
) B
;
All you have to do is set the Cookieid in both subqueries.
Make sure you have this index:
ALTER TABLE Table1 ADD INDEX Cookieid_Name_ndx (Cookieid,Name);