3 tables, left join, in case DATA is missing in ONE table - php

table1 (ids always exist)
+----+------+
| id | col1 |
+----+------+
| 1 | ab |
+----+------+
| 2 | gh |
+----+------+
table2 (ids always exist)
+----+------+
| id | col2 |
+----+------+
| 1 | cd |
+----+------+
| 2 | ij |
+----+------+
table3 (ids might be missing, in this case 2 is missing)
+----+------+
| id | col3 |
+----+------+
| 1 | ef |
+----+------+
PHP
$col = 'ab';
$a = mysql_query("SELECT t1.id FROM table1 AS t1, table2 AS t2, table3 AS t3
WHERE t1.id = t2.id AND t2.id = t3.id AND (t1.col1 = '$col' OR t2.col2 = '$col'
OR t3.col3 = '$col) GROUP BY t1.id, t2.id, t3.id");
That would only work if all three tables had "the same id" included, but what happens if an "id" is missing in table3 for whatever reason? how can I still test for all three tables and get t1.id to output 1, when $col = ab? would I have to use left join?
$a = mysql_query("SELECT t1.id FROM table1 AS t1, table2 AS t2
LEFT JOIN (SELECT id FROM table3 WHERE col3 = '$col') AS t3 ON t3.id = t1.id
WHERE t1.id = t2.id AND (t1.col1 = '$col' OR t2.col2 = '$col')
GROUP BY t1.id, t2.id");
what am I doing wrong here?

What are you doing wrong? Querying a table that doesn't exist. That's always going to raise an error.
I'm not going to address the wisdom of designing a database in which tables crucial to your queries come and go.
Your only hope on the client side is to
test for the existence of the tables
you're interested in, and
execute different SQL statements
based on those results.
[After your edit]
It sounds like you need either one or two left outer joins. This gives you all the ids that are common to both table1 and table2, regardless of whether they're in table3.
select t1.id, t2.id, t3.id
from table1 t1
inner join table2 t2 on (t1.id = t2.id)
left join table3 t3 on (t1.id = t3.id);
And this gives you all the ids that are in table1, regardless of whether they're in table2 or table 3.
select t1.id, t2.id, t3.id
from table1 t1
left join table2 t2 on (t1.id = t2.id)
left join table3 t3 on (t1.id = t3.id);
And, of course, you can filter the results with your WHERE clause.

LEFT JOIN only works when the table DOES exist, but contains no data.
If you don't want to have to do stuff like Catcall suggested (check if the table exists, and use different SQL statements based on that...) you have to make sure that the table exists in the database, even if it's completely empty.
Under normal circumstances, you should have a certain degree of control over your application's database, so you should be able to make sure that the table is really there.
If this is really a big problem (like, that you can't be sure if someone deleted the table) you could check this every time you start your application: create the table if it doesn't exist.

Related

Mysql php: How to join same table multiple times?

Team table has:
ID | TEAM
--------+----------
1 | A
2 | B
Result table has:
fk_ID1 | fk_ID2 | RESULT
----------+-----------+-----------
1 | 2 | 5:0
2 | 1 | 2:3
How to Inner JOIN table, to get: (A 5:0 B) & (A 2:3 B)?
My code example:
public function getResultList($limit, $offset) {
$query = " SELECT result_id,
t1.name name1,
t2.name name2,
team1_goals,
team2_goals,
date
FROM results
INNER JOIN team t1 ON fk_tm1_id=tm_id
INNER JOIN team t2 ON fk_tm2_id=tm_id";
$data = mysql::select($query);
return $data;
}
It's best to answer this as purely an SQL question, which it is. You need to assign a table alias when joining the same table two or more times.
You seem to only be assigning aliases to the column. To assign an alias to a column or table, you can add the alias directly after the column or table name (AS can also be used but isn't necessary for MySQL)
A common thing is to number the tables as t1, t2, t3, etc.
SELECT t1.name name1, t2.name name2 FROM ...
INNER JOIN team_table t1 ON ...
INNER JOIN team_table t2 ON ...
This aliases the first join as t1 and the second join as t2, which you would use when accessing data from that specific join (SELECT t1.name).

How to join this 5 tables in mysql?

I have 5 tables that I need to connect to get the necessary data.
Table1
id | number
1 | 1
2 | 5
Table 2
id | number | user_id
1 | 1 | 9
2 | 5 | 8
Table 3
id | name |
8 | john |
9 | jane |
Table 4
id | email
6 | johndoe#example.com
Table 5
id | table4_id | table3_id
1 | 6 | 8
Table 1 is my main table and I want to add the name and email from table 3 and 4 respectively to my select query of table 1, but in order to do so, I would need to use table 2 and 5 to connect them as there is no direct relationship between table 1 and table 3 and 4. I only know how to join 3 tables and not 5 tables and it seems confusing to me on how to proceed with this.
I followed the link here to join Table 1,2 and 3. But I don't know how to proceed with table 4 and 5.
This is the query I tried:
SELECT table1.number, table2.number, table2.user_id, table3.id, table3.name,
table4.id, table4.email, table5.table4_id, table3_id
FROM table1
LEFT JOIN table2
INNER JOIN table3
//this query will work if I don't include this 2 inner joins
INNER JOIN table4
INNER JOIN table5
ON table3.id = table5.table3_id
ON table5.table4_id = table4.id
//
ON table2.user_id= table3.id
ON table2.number = table1.number;
ERROR: (if included the inner join for table 4 and 5)
Error Code: 1064. You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right
syntax to use near 'ON table2.user_id= table3.id
The right Syntax is select .. from .. join .. on .. join ..on ....
SELECT table1.number, table2.number, table2.user_id, table3.id, table3.name, table4.id, table4.email, table5.table4_id, table3_id
FROM table1
LEFT JOIN table2 ON table2.number = table1.number
INNER JOIN table3 ON table2.user_id= table3.id
INNER JOIN table5 ON table3.id = table5.table3_id
INNER JOIN table4 ON table5.table4_id = table4.id
Try with the below structure. I made it from the structure you given in question
select t1.number, t2.number, t2.user_id, t3.id, t3.name,t4.id, t4.email, t5.t4_id, t3_id
from table5 as t5
join table4 as t4 on t5.table4_id = t4.id
join table3 as t3 on t5.table3_id=t3.id
join table2 as t2 on t2.user_id = t3.id
join table1 as t1 on t2.number=t1.number
Try Below code. Hope this will work.
Select t3.name,t4.email,t1.number,t2.user_id
from table3 t3 JOIN table5 t5 ON t3.id=t5.table3_id
JOIN table4 t4 ON t4.id=t5.table4_id
JOIN table2 t2 ON t2.user_id=t3.id
JOIN table1 t1 ON t1.number=t2.number;

Get all results from mysql JOIN, even if no join matches

I am doing a JOIN operation between a table and itself. The table schema is something like:
| id | name | parent |
| 0 | .... | ... |
| 1 | .... | ... |
| 2 | .... | ... |
The query looks like:
$qMarks = str_repeat('?,', count($arr) - 1) . '?';
$stmt = $db->prepare("SELECT t1.id AS t1id, t1.name AS t1name, t2.name AS t2name
FROM cats t1
JOIN cats t2 ON t1.parent = t2.id
WHERE t1.name IN ($qMarks)");
$stmt->execute($arr);
$result = $stmt->fetchAll();
So, I'm passing in an array of names $arr, and I am getting back the rows where there is a matching name to one of the items in the parameter array. This works fine, so long as there is also a matching id somewhere for parent.
But, sometimes the value for parent will be blank (empty cell). I still want to get those results, as long as the t1.name IN ($qMarks) condition is met.
How do I return the values, even if the t1.parent value in the table is blank?
Use a left join.
$stmt = $db->prepare("SELECT t1.id AS t1id, t1.name AS t1name, t2.name AS t2name
FROM cats t1
LEFT JOIN cats t2 ON t1.parent = t2.id
WHERE t1.name IN ($qMarks)");

Displaying Inner joined table has different values in 1 column

Hello! I need help i have table that has this value
Table1
sorter | valuedata | status | useraccounts |
----------------------------------------------
same | value1 | Disabled | user1 |
same | value2 | Active | user1 |
And
Table2
name | useraccounts |
-------------------------
user1 | displayname1 |
and I wanted to display all the data even they have different status while they are innerjoin like this
SELECT table1.name,table2.useraccounts
FROM table1 INNER JOIN table2 ON table1.useraccounts = table2.name
WHERE table1.sorter = "same" AND table1.status = "Disabled" AND table1.status != "Disabled"
is this even possible to do??
I think you made 2 mistakes:
table 1 does not have name column
what you are look for is an OR instead of AND.
The next is what I think you are looking for:
SELECT table2.[name],table2.useraccounts
FROM table1 INNER JOIN table2 ON table1.useraccounts = table2.name
WHERE table1.sorter = 'same' AND
(table1.status = 'Disabled' OR table1.status != 'Disabled')
and this can be rewritten to the next since checking for 'Disabled' or != 'Disabled' is ALL ROWS.
SELECT table2.[name],table2.useraccounts
FROM table1 INNER JOIN table2 ON table1.useraccounts = table2.name
WHERE table1.sorter = 'same'
Actually, you need the cross join. You can write it without using the JOIN as well:
SELECT table2.name,table2.useraccounts
FROM table1,table2 WHERE table1.useraccounts = table2.name
AND table1.sorter = "same"
SELECT table2.name,table1.useraccounts
FROM table1 INNER JOIN table2 ON table1.useraccounts = table2.name
U will get all data while status is differnt or not

CodeIgniter Self-Join doesn't match SQL

Alright, have to be missing something here.
My SQL works fine:
SELECT t1.id, t1.material, t2.id, t2.material, t3.id, t3.material, t4.id, t4.material
FROM ml_levels t1
LEFT JOIN ml_levels t2
ON t1.parentID = t2.id
LEFT JOIN ml_levels t3
ON t2.parentID = t3.id
LEFT JOIN ml_levels t4
ON t3.parentID = t4.id
WHERE t1.id = 286
This returns
id | material | id | material | id | material | id | material
-------------------------------------------------------------------------------------------
286 | 4Layer | 209 | Protective Film | 60 | Specialty Products | 1 | Protect
However, my ActiveRecord is only returning t4.id and t4.material:
$this->db->select('t1.id, t1.material, t2.id, t2.material, t3.id, t3.material, t4.id, t4.material');
$this->db->from('ml_levels AS t1')->where('t1.id',286);
$this->db->join('ml_levels AS t2','t1.parentID = t2.id','left');
$this->db->join('ml_levels AS t3','t2.parentID = t3.id','left');
$this->db->join('ml_levels AS t4','t3.parentID = t4.id','left');
return $this->db->get()->row();
this returns:
id | material |
-------------------
1 | Protect |
$this->db->last_query() returns:
SELECT `t1`.`id`, `t1`.`material`, `t2`.`id`, `t2`.`material`, `t3`.`id`, `t3`.`material`, `t4`.`id`, `t4`.`material`
FROM (`ml_levels` AS t1)
LEFT JOIN `ml_levels` AS t2 ON `t1`.`parentID` = `t2`.`id`
LEFT JOIN `ml_levels` AS t3 ON `t2`.`parentID` = `t3`.`id`
LEFT JOIN `ml_levels` AS t4 ON `t3`.`parentID` = `t4`.`id`
WHERE `t1`.`id` = 286
And if I run this SQL on the database, it returns exactly what the original query returned.
Codeigniter return only field name without table label so that you found only two fields because there are only id and material. Change line:
$this->db->select('t1.id, t1.material, t2.id, t2.material, t3.id, t3.material, t4.id, t4.material');
with:
$this->db->select('t1.id AS t1id, t1.material AS t1material, t2.id AS t2id, t2.material AS t2material, t3.id AS t3id, t3.material AS t3material, t4.id AS t4id, t4.material AS t4material');

Categories