MySQL Query to combine two tables - mysql

I'm trying to get a MySQL query to combine two tables. Both tables have a user_id and date column and the other columns are unique to each table. What I'm looking to accomplish is best explained with an image (imgur). I've tried various joins and unions and can't get the right combination. I've also tried searching stackoverflow but I'm likely not using the right terminology for what I'm looking to do.
The description of the tables in TEXT:
tablel
user_id date animals
1 9/15/2020 Lion
2 8/11/2020 Tiger
3 12/12/2020 Bear
table2
user_id date fruit
1 7/7/2020 apple
2 6/5/2020 pear
4 3/8/2020 peach
output
user_id date animals fruit
1 9/15/2020 Lion
1 7/7/2020 apple
2 8/11/2020 Tiger
2 6/5/2020 pear
3 12/12/2020 Bear
4 3/8/2020 peach

With UNION ALL you can achieve that
SELECT user_id, date, animals, fruit FROM
(
SELECT user_id, date, animals, '' as fruit
FROM table1
UNION ALL
SELECT user_id, date, '', fruit
FROM table2
) t
ORDER BY user_id, animals

You may also try FULL OUTER JOIN:
SELECT user_id, date, animals, '' as fruit
FROM table1
FULL OUTER JOIN table2
ON table1.user_id = table2.user_id AND table1.date = table2.date

-- use test;
-- drop table if exists table1;
create table table1(user_id int, `date` date, animals varchar(10));
insert into table1 values(1,'2020/09/15','Lion');
insert into table1 values(2,'2020/11/08','Tiger');
insert into table1 values(3,'2020/12/12','Bear');
-- drop table if exists table2;
create table table2(user_id int, `date` date, fruit varchar(10));
insert into table2 values(1,'2020/07/07','apple');
insert into table2 values(2,'2020/05/06','pear');
insert into table2 values(4,'2020/08/03','peach');
select
user_id,
`date`,
animals,
'' as fruit
from table1
union all
select
user_id,
`date`,
'',
fruit
from table2
order by user_id,`date`;
output:
+ ------------ + --------- + ------------ + ---------- +
| user_id | date | animals | fruit |
+ ------------ + --------- + ------------ + ---------- +
| 1 | 2020-07-07 | | apple |
| 1 | 2020-09-15 | Lion | |
| 2 | 2020-05-06 | | pear |
| 2 | 2020-11-08 | Tiger | |
| 3 | 2020-12-12 | Bear | |
| 4 | 2020-08-03 | | peach |
+ ------------ + --------- + ------------ + ---------- +

the more simple query to understand it would be :
SELECT * FROM tablel, table2 WHERE table1.user_id = table2.user_id
the second table need to have a foreign key, that have the id like the fisrt table, this query that I show you works like a INNER JOIN.

Related

INNER JOIN on One Table but different Parameter

I am trying to get different values on rows of one table, and I can't think of how to that.
Lets say for example:
table1
id | name | empCode | insCode
1 John | E101 | I101
table2
id | code | name | role
1 | E101 | Mich | 2
2 | I101 | Bran | 3
table1 has reference id of table2, and empCode and insCode in table1 dependes on code and role in table2.
What I want is like this:
id | code | name | empCode | insCode | role |
1 | ? | John | E101 | I101 | ? |
I honestly don't know if its possible to retrieve multiple rows in same table in one select query.
If its not, what other possible solutions can I go with?
There is problem in your table design but you can get as your expected with below query:
select
result1.id,
result1.code,
result1.name,
result1.empCode,
result1.insCode,
result1.role as role_of_empCode,
result2.role as role_of_insCode
from (
SELECT tbl1.id,
tbl2.code,
tbl1.name,
tbl1.empCode,
tbl1.insCode,
tbl2.role
FROM `table2` tbl2
INNER JOIN `table1` tbl1
on tbl2.code = tbl1.empCode
) as result1,
`table2` result2
where result1.insCode = result2.code
ORDER BY result1.id;
You can check in this link!
Try something like:
SELECT a.*, b.role FROM
table1 a inner join table2 b on a.id=b.id
Also you may want to consider removing empcode and inscode from table 2 since its being redundant in table 1 OR vice versa depending on what your objectives are.

Joining multiple tables into a single mysql table adding new field to each record

i have a question about mysql. I have multiple tables (Dresden, dusseldorf, England, etc) each one of this have the following fields (Name, loginname, macaddress). Some users are in more than one table (the same user can be in two or more of this tables.) I want to create a table where i can see all users. I was wondering if it is possible to add a field at the end of each raw telling where if come from and to merge all repeated files. I hope i made myself clear.... i am really new to mysql....
Best regards...
Here are my tables:
Dusseldorf:
--------------------------------
|Username | value | macaddress |
-------------------------------
|jose | 10 | 00:00:00:00|
--------------------------------
|maria | 20 | 00:00:00:01|
--------------------------------
Dresden:
--------------------------------
|Username | value | macaddress |
--------------------------------
|jose | 10 | 00:00:00:00|
--------------------------------
|maria | 20 | 00:00:00:01|
--------------------------------
|juan | 15 | 00:00:00:02|
--------------------------------
England:
--------------------------------
|Username | value | macaddress |
-------------------------------
|jose | 10 | 00:00:00:00|
-------------------------------
|maria | 20 | 00:00:00:01|
--------------------------------
|pedro | 20 | 00:00:00:03|
--------------------------------
All together:
-----------------------------------------------------------------
|Username | value | macaddress | Dusseldorf | Dresden | England |
-----------------------------------------------------------------
|jose | 10 | 00:00:00:00| X | X | X |
-----------------------------------------------------------------
|maria | 20 | 00:00:00:01| X | X | X |
-----------------------------------------------------------------
|juan | 15 | 00:00:00:02| | X | |
-----------------------------------------------------------------
|pedro | 20 | 00:00:00:03| | | X |
-----------------------------------------------------------------
You could select this data with several UNION statements and use a CREATE TABLE to create the new table:
CREATE TABLE all_merged AS
SELECT s.*,
concat((SELECT 'Dresden'
FROM Dresden
WHERE Dresden.name=s.name
AND Dresden.loginname = s.loginname
AND Dresden.macaddress = s.macaddress
),
(SELECT 'Dusseldorf'
FROM Dusseldorf
WHERE Dresden.name=s.name
AND Dresden.loginname = s.loginname
AND Dresden.macaddress = s.macaddress
),
...) as `location`
FROM
( SELECT name, loginname,macaddress
FROM Dresden
UNION
SELECT name, loginname,macaddress
FROM Dusseldorf
UNION
....
) AS S
)
Althought I thing that building a view could be better for your case:
CREATE VIEW v_all_merged AS
SELECT s.*,
concat((SELECT 'Dresden'
FROM Dresden
WHERE Dresden.name=s.name
AND Dresden.loginname = s.loginname
AND Dresden.macaddress = s.macaddress
),
(SELECT 'Dusseldorf'
FROM Dusseldorf
WHERE Dresden.name=s.name
AND Dresden.loginname = s.loginname
AND Dresden.macaddress = s.macaddress
),
...) as `location`
FROM
( SELECT name, loginname,macaddress
FROM Dresden
UNION
SELECT name, loginname,macaddress
FROM Dusseldorf
UNION
....
) AS S
)
I just created a sqlfiddle to show the solution
This seems to be what you are looking for. Build a new table based on the others with one additional field for the origin:
create table users as
select name, loginname, macaddress, 'Dresden' as origin from dresden
union all
select name, loginname, macaddress, 'Düsseldorf' as origin from dusseldorf
union all
select name, loginname, macaddress, 'England' as origin from england
...
Of course instead of storing the same origin string again and again you should have two tables instead (but using the same technique):
create table origins(id int, origin varchar(30));
insert into table origins (1, 'Dresden');
insert into table origins (2, 'Düsseldorf');
...
create table users as
select name, loginname, macaddress, 1 as id_origin from dresden
union all
select name, loginname, macaddress, 2 as id_origin from dusseldorf
...
You can create a table with concatenated location strings as follows. Though I recommend better have three separate tables for users, locations and their relation.
create table users as
select
loginname,
max(name) as name,
max(macaddress) as macaddress,
group_concat(location) as locations
from
(
select name, loginname, macaddress, 'Dresden' as location from dresden
union all
select name, loginname, macaddress, 'Düsseldorf' as location from dusseldorf
union all
select name, loginname, macaddress, 'England' as location from england
...
);

can i use GROUP_CONCAT to update table?

can i use GROUP_CONCAT to update table? I have 2 tables
i
d | label
------------------------------
1 | ravi,rames,raja
------------------------------
2 | ravi
------------------------------
3 | ravi,raja
------------------------------
4 | null
------------------------------
5 | null
------------------------------
6 | rames
------------------------------
and
id | values
------------------------------
12 | raja
------------------------------
13 | rames
------------------------------
14 | ravi
------------------------------
And i want the result like following table--
id | label
------------------------------
1 | 12,13,14
------------------------------
2 | 14
------------------------------
3 | 14,12
------------------------------
4 | null
------------------------------
5 | null
------------------------------
6 | 13
------------------------------
but by using the following query -
SELECT `table1`.`id`, GROUP_CONCAT(`table2`.`id` ORDER BY `table2`.`id`) AS label
FROM `table1`
JOIN `table2` ON FIND_IN_SET(`table2`.`values`, `table1`.`nos`)
GROUP BY `table1`.`id`;
Im getting-
id | label
------------------------------
1 | 12,13,14
------------------------------
2 | 14
------------------------------
3 | 12,14
------------------------------
6 | 13
------------------------------
I want to keep the null value. otherwise the order of rows will be broken. please help.
sorry for the large font :(
You just need a LEFT JOIN to preserve the nulls:
SELECT `table1`.`id`, GROUP_CONCAT(`table2`.`id` ORDER BY `table2`.`id`) AS label
FROM `table1`
LEFT JOIN `table2` ON FIND_IN_SET(`table2`.`values`, `table1`.`nos`)
GROUP BY `table1`.`id`;
However, I recommend against updating a table to include comma-separated values in a column. It forces you to use FIND_IN_SET() when querying it, and breaks the ability to index the column, affecting the performance of your queries. The more sustainable action would be to normalize table1 so that it doesn't include a comma-separated column.
Update:
To use GROUP_CONCAT() in an UPDATE statement, you would use a syntax like the following. Substitute your correct table and column names, and in your case, you probably want to replace the entire JOIN subquery with your SELECT statement.
UPDATE
tbl_to_update
JOIN (SELECT id, GROUP_CONCAT(concatcolumn) AS label FROM tbl GROUP BY id) tbl_concat
ON tbl_to_update.id = tbl_concat.id
SET tbl_to_update.column_to_update = tbl_concat.label
WHERE <where condition>
So in your case:
UPDATE
table1
INNER JOIN (SELECT id, GROUP_CONCAT(id) AS label FROM table1 GROUP BY id) table2
ON FIND_IN_SET(`table2`.`label`, `table1`.`nos`)
SET table1.nos = table2.id

Why is this two table into one table union, where showing invalid result in MySQL?

I have a table1 (records 3), and table2 (records 3).
Where i have field name in both.
Now i want to make a result from those two table
which will show me both table records and take only one if there is duplicate.
from that result i will do main query using like or or other logical statements
So my expected output records will contain 5 rows not 6 rows. How do i do that?
Example:
table1: table2:
+-------------------------+ +--------------------------------+
| Name | ID | Name | ID
+-------------------------- +---------------------------------
| A | 1 | 1 December Name | 4
| B | 2 | D | 5
| 1 December Name | 3 | E | 6
My Expected output is following which works, but does not work when i use WHERE
like to only get '1 December Name':
+-----------------------------------------------------+
| Name | ID
+-----------------------------------------------------
| A | 1 table1
| B | 2 table1
| 1 December Name | 3 table2 or table1 (no unique)
| D | 4 table2
| E | 5 table2
I tried this:
SELECT * FROM
(
(
SELECT name AS name FROM table1
)
UNION
(
SELECT anothername AS name FROM table2
)
) as t
WHERE name like '%1 December Name%'
limit 1,10
Output: Your SQL query has been executed successfully ( Query took 0.2798 sec )
Problem: The following query has no error but it does not find that record which contain '1 December Name'
Follow up: works i know now which ID it used
SELECT NAME, ID, STATUS FROM
(
(
SELECT NAME AS name , id, CONCAT('table1') AS STATUS FROM table1
)
UNION ALL
(
SELECT ANOTHERNAME AS name, id, CONCAT( 'table2' ) AS STATUS FROM table2
)
) AS t
WHERE
t.NAME LIKE '%1 December Name%'
LIMIT 1 , 10;
You can get something similar to what you want:
select name, group_concat(id) from
(select name, 'table1' as id from table1
union all
select name, 'table2' from table2) x
group by name
Output would be:
+------------------------------------+
| Name | ID
--------------------------------------
| A | table1
| B | table1
| 1 December Name | table1,table2
| D | table2
| E | table2
UNION ALL is the right choice (not UNION), because it does not remove duplicates, and preserves row order
Try this
(SELECT name FROM table1 )
UNION (SELECT name FROM table2);

SQL: How to return an non-existing row?

Say I have the following table:
=================================================
| color_id | parent_id | language_id | name |
=================================================
| 1 | 50 | 1 | Black |
-------------------------------------------------
Then say I need the row WHERE parent_id = 50 AND language_id = 2. Obviously, I would get nothing back based on my example table. However, I still need a result -- probably something like this:
=================================================
| color_id | parent_id | language_id | name |
=================================================
| NULL | 50 | 2 | NULL |
-------------------------------------------------
Is there a way to do this in SQL?
You could do a union query of both the potentially valid record and your default, then select the first one:
SELECT * FROM
(SELECT color_id, parent_id, language_id, name, 1 as order_rank
FROM some_table
WHERE parent_id = %parent_id% AND language_id = %language_id%
UNION
SELECT NULL, %parent_id%, %language_id%, NULL, 2 as order_rank
)
ORDER BY order_rank
LIMIT 1
(Edited with static value for ordering as suggested by OMG Ponies)
try working with LEFT JOIN statement. i'm probably not doing this 100% but a bit of trial and error on your part should make this work.
SELECT table1.field1, table1.field2, table2.field3, table2.field4
FROM my_table table1
LEFT JOIN my_table table2 ON table1.field1=table2.field1 OR table1.field2=table2.field2
a left join on a forced fixed value first table SHOULD work.
select
YourTable.color_id,
ForcedSQL1Record.parent_id,
ForcedSQL1Record.language_id,
YourTable.name
from
( select 50 as Parent_ID,
2 as Language_ID
from YourTable
limit 1 ) ForcedSQL1Record
left join
YourTable
on ForcedSQL1Record.Parent_ID = YourTable.Parent_ID
AND ForcedSQL1Record Language_ID = YourTable.Language_ID