I have a couple of tables that look like this.
table_a | table_b
-------------------------
prim_key | prim_key
zero_or_one | value1
valueA | value2
valueB | value3
valueZ |
What I'm hoping to do is retrieve all of the values (prim_key, value1, value2, value3) from TABLE B if the primary keys of each table match and the value of zero_or_one in TABLE A is 0.
I'm completely new to joins, and I'm not exactly sure which join I should be using for this, but it seems like a FULL OUTER JOIN is most appropriate.
SELECT table_b.*
FROM table_a
FULL OUTER JOIN table_b
ON table_a.prim_key = table_b.prim_key
Is this even possible?
Am I using the right join for the job?
Is my "select all" syntax correct?
Since you want entries from table_b only when there is a matching primary key found in the table_a; a simple Inner Join would suffice in this case
SELECT table_b.*
FROM table_b
INNER JOIN table_a
ON table_a.prim_key = table_b.prim_key AND
table_a.zero_or_one = 0
This answer is not meant als a real answer this is meant how to simulate FULL OUTER JOIN in MySQL.
FULL OUTER JOIN is not supported in MySQL you can simulate it with a LEFT JOIN, UNION ALL and RIGHT JOIN
SELECT * FROM table_a LEFT JOIN table_b ON table_a.prim_key = table_b.prim_key
UNION ALL
SELECT * FROM table_a RIGHT JOIN table_b ON table_a.prim_key = table_b.prim_key
WHERE table_a.prim_key IS NULL
Related
I have three data tables that have the same length (~50000), different columns (<500 each), and share a common "id" column.
They look like:
table A
id A1 A2 ...
1 xxx xxx ...
2 xxx xxx ...
... ... ... ...
n xxx xxx ...
table B
id B1 B2 ...
1 xxx xxx ...
2 xxx xxx ...
... ... ... ...
n xxx xxx ...
table C
id C1 C2 ...
1 xxx xxx ...
2 xxx xxx ...
... ... ... ...
n xxx xxx ...
I was trying to join them together using
CREATE TABLE my_table
SELECT *
FROM table_A
LEFT OUTER JOIN table_B
ON table_A.id = table_B.id
LEFT OUTER JOIN table_C
ON table_A.id = table_C.id;
and it's been taking hours.
However, when I do it by two separate steps like
CREATE TABLE my_table_0
SELECT *
FROM table_A
LEFT OUTER JOIN table_B
ON table_A.id = table_B.id;
CREATE TABLE my_table_1
SELECT *
FROM my_table_0
LEFT OUTER JOIN table_C
ON my_table_0.id = table_C.id;
Each "step" only takes less than 5 minutes.
Does anyone know whether this is normal and what's causing it? I wonder if there is a faster way I can join three tables altogether without creating intermediary tables.
Sometimes (My)SQL can be strange.
What maybe already could help in your case is using an inner join, if i understand this correctly all tables share the id column so this should be already a bit faster.
To get a better understanding about what is going on when you execute your query you can use the EXPLAIN keyword, there are some articles using it and understanding the output.
For example this is a good read: https://www.exoscale.com/syslog/explaining-mysql-queries/
When doing a UNION of 2 tables, you should use FULL OUTER JOIN. Would you try to execute below codes and let me know if it works:
CREATE TABLE my_table
SELECT *
FROM table_A
FULL OUTER JOIN table_B
ON table_A.id = table_B.id
FULL OUTER JOIN table_C
ON table_A.id = table_C.id;
And if you would like to join the 3 tables while maintaining the length of the first table (same number of rows), you should use LEFT JOIN:
CREATE TABLE my_table
SELECT *
FROM table_A
LEFT JOIN table_B
ON table_A.id = table_B.id
LEFT JOIN table_C
ON table_A.id = table_C.id;
Depending on the SQL software, not all would understand LEFT OUTER JOIN.
Try to use either OUTER JOIN or LEFT JOIN.
I have the following tables:
TABLE A
id
info
TABLE B
f_id
question
choices
TABLE C
f_id
question
lines
The id from the Table A always match a f_id from either Table B or C, but never both. I want to join Table B and Table C on table A only when it matches so I would get a table with the following columns :
id | info | question | choices | lines
where all rows are filled in the question column, some are NULL in the column choices and some are NULL in the column lines.
What I tried is to do two consecutive left joins, but the second one overrides the first so all the rows that doesn't match in Table C (second left join) get a NULL value in the question column.
Is there a way to do a query that will not override previously joined data with NULL values? I'm working with Laravel Eloquent, so any of raw SQL or Eloquent Query would help me.
UNION B and C and then INNER JOIN A to those results.
SELECT s1.f_id, s1.question, s1.choices, s1.lines
FROM
(
SELECT f_id, question, choices, lines = null
FROM B
UNION
SELECT f_id, question, choices = null, lines
FROM C
) s1
INNER JOIN A ON s1.f_id = A.id
but never both
Good luck with that.
id | info | question | choices | lines
SELECT a.id, a.info, b.question, b.choices, '' AS lines
FROM tableA as A
LEFT JOIN tableB AS b
ON a.id=b.f_id
UNION
SELECT a.id, a.info, c.question, '', c.lines
FROM tableA as A
INNER JOIN tableC AS c
ON a.id=c.f_id
You could use UNION to combine two different queries.
SELECT
`id`, `info`, `question`, `choices` AS `lines`
FROM
`TABLE_A` INNER JOIN
`TABLE_B` ON `TABLE_A`.`id` = `TABLE_B`.`f_id`
UNION
SELECT
`id`, `info`, `question`, `lines`
FROM
`TABLE_A` INNER JOIN
`TABLE_C` ON `TABLE_A`.`id` = `TABLE_C`.`f_id`
Make sure to use JOIN or INNER JOIN (JOIN defaults to INNER JOIN on MySQL) AND not LEFT JOIN, RIGHT JOIN, OUTER JOIN otherwise you'll end up with partially filled results.
I m trying to fetch data from 2 table aisle and type. The aisle table has following construct:
aisle_id | name | x | y
and the type table has following construct
type_id | name | aisle_id (FK)
aisle_id is the foreign key.
I'm using this sql query which works but, not as expected:
SELECT NAME,X, Y FROM type, aisle where Name ="bread"
What this statement returns me is, it returns bread but also returns all the data from the X and Y, which i do not want, I just want the x and y related to bread. So could anyone help?
Thank you
Try joining the two on aisle_id as below:
SELECT t.Name, a.X, a.Y
FROM aisle a INNER JOIN type t
ON a.aisle_id = t.aisle_id
WHERE a.Name ="bread"
With a simple Google search, and since you know what you need (join), the first result came directly from MySQL documentation:
Some join examples:
SELECT * FROM table1, table2;
SELECT * FROM table1 INNER JOIN table2 ON table1.id=table2.id;
SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id;
SELECT * FROM table1 LEFT JOIN table2 USING (id);
SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id
LEFT JOIN table3 ON table2.id=table3.id;
In your case it would be:
SELECT aisle.NAME, aisle.X, aisle.Y FROM type JOIN aisle ON type.type_id = aisle.type_id WHERE aisle.Name ="bread"
i have a table called users contained
(Table A)
Users
user_id
username
user_type[1,2]
(Table B) if user_type=1
user_id
full_name
(Table C) if user_type=2
user_id
full_name
i want to get single record set by executing single query, is that possible in PHP mysql.
Try this:
SELECT table_a.*, COALESCE(table_b.full_name,table_c.full_name) AS full_name
FROM table_a
LEFT OUTER JOIN table_b ON table_b.user_id = table_a.user_id
LEFT OUTER JOIN table_c ON table_c.user_id = table_a.user_id WHERE 1;
It uses the LEFT OUTER JOIN, which means that it joins it to table_b on the given condition. However, for each row in table_a, whether it finds a matching row in table_b or not, it will return the table_a row. If it does not find a matching row, the table_b columns are just NULL. Same thing with table_c.
Then, we just select all the table_a columns. However, we now have two full_name columns, one from table_b and one from table_c. We use COALESCE to merge them.
COALESCE returns the first non-NULL value.
Since we know that there is either a matching row in table_b or a matching row in table_c, it is not a problem. However, it would be a problem if somehow you allows a matching row to be found in both table_b and table_c.
The risk can be mitigated by adding additional ON clause conditions to get:
SELECT table_a.*, COALESCE(table_b.full_name,table_c.full_name) AS full_name
FROM table_a
LEFT OUTER JOIN table_b
ON table_b.user_id = table_a.user_id AND table_a.user_type = 1
LEFT OUTER JOIN table_c
ON table_c.user_id = table_a.user_id AND table_a.user_type = 2
WHERE 1;
Still, you will need to make sure only 1 row is present for each user in table_b and table_c.
Instead of COALESCE you can optionally use CASE like:
SELECT table_a.*, CASE user_type WHEN 1
THEN table_b.full_name
ELSE table_c.full_name END AS full_name
...
or use an IF function like:
SELECT table_a.*, IF(user_type=1,table_b.full_name,table_c.full_name) AS full_name
...
You can UNION both tables and later on JOIN it with tableA
SELECT a.User_ID,
a.`username`,
b.full_name,
a.user_type
FROM tableA a
(
SELECT user_ID, full_name
FROM tableB
UNION
SELECT user_ID, full_name
FROM tableC
) b ON a.User_ID = b.User_ID
-- WHERE a.user_type = 1 -- add extra condition here
I'm working on joining 3 tables.
table1.
grp_id | email_id
1 | 3
1 | 58
table2.
sam_msg_id | sam_subject
3 | Funnel
table3.
id | subject
58 | testing check
Desired Output:
id |grp_id|email_id|sam_subject|subject |
184|1 |3 |funnel | |
185|1 |58 | |testing check|
the query I tried:
SELECT table1.*, table2.sam_subject, table3.*
FROM table1
INNER JOIN table2
ON table2.sam_msg_id = table1.email_id
INNER JOIN table3
ON table3.id = table1.email_id
WHERE table1.grp_id = '1'
What I'm trying to do here is to get the list of subject and its id from table2 and table3 where the id is found at table1 under email_id.
When I tried doing it with one inner join only by checking only the data from table2 it was working.
I am not familiar in using inner joins thus I can't really see what I'm doing wrong.
I am using MySQL.
Sounds like you need a LEFT JOIN
SELECT table1.*, table2.sam_subject, table3.*
FROM table1
LEFT JOIN table2
ON table2.sam_msg_id = table1.email_id
LEFT JOIN table3
ON table3.id = table1.email_id
WHERE table1.grp_id = '1'
Based on you edit, the following should give you the results you want:
SELECT t1.grp_id,
t1.email_id,
coalesce(t2.sam_subject, '') sam_subject,
coalesce(t3.subject, '') subject
FROM t1
left JOIN t2
ON t2.sam_msg_id = t1.email_id
left JOIN t3
ON t1.email_id = t3.id
WHERE t1.grp_id = '1'
See SQL Fiddle with Demo
I'm a bit confused about what you are asking. If you can provide an example of your current data and your desired output we can probably nail down a solution.
As it is, I suspect you need to read up on LEFT JOIN, which will return NULL if there is no matching record in your child table. INNER JOIN will not return a record if there is no match.
Take a look at this article for an explanation of the different types of joins:
http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html
UPDATE:
I'm not sure where the first column of your desired results is coming form but the query below should get you the desired results:
SELECT t1.*, t2.sam_subject, t3.subject
FROM Table1 as t1
LEFT JOIN table2 as t2
on t1.email_id = t2.sam_msg_id
LEFT JOIN table3 as t3
on t1.email_id = t3.id