Left Join multiple times 2 tables using same column ON - php

I have a table A where several columns values should be replaced from corresponding id which are stored in table B as in this scheme:
TABLE_A
object_id desc_id_1 desc_id_2 desc_id_3 desc_id_4
zxy_34 9999 9567 5555 5556
TABLE_B
desc_id complete_desc
1234 ABCD
9999 ZYXW
9567 POTG
5555 YUNR
5556 LPVR
……..
……..
Final show than should be like that:
object comp_desc_1 comp_desc_2 comp_desc_3 comp_desc_4
zxy_34 ZYXW POTG YUNR LPVR
Is it possible?
At the moment tried something like that:
$sql="SELECT table_a.object_id, table_b.complete_desc
FROM table_a
LEFT JOIN table_b ON table_a.desc_id_1 =table_b.complete_desc";
It works ok using output this way:
echo "<table border='1'>
<tr>
<th>object</th>
<th>comp_desc_1 </th>
</tr>";
while($row = mysqli_fetch_array($result)) {
echo "<tr>";
echo "<td>" . $row['object_id '] . "</td>";
echo "<td>" . $row['desc_id_1 '] . "</td>";
echo "</tr>";
}
echo "</table>";
The problem is that don’t really know how to go further.
Adding another left join like that stop the script and make load a blank page:
$sql="SELECT table_a.object_id, table_b.complete_desc, table_b.complete_desc
FROM table_a
LEFT JOIN table_b ON table_a.desc_id_1 =table_b.complete_desc
LEFT JOIN table_b ON table_a.desc_id_2 =table_b.complete_desc ";
…..
echo "<table border='1'>
<tr>
<th>object</th>
<th>comp_desc_1 </th>
<th>comp_desc_2 </th>
</tr>";
while($row = mysqli_fetch_array($result)) {
echo "<tr>";
echo "<td>" . $row['object_id '] . "</td>";
echo "<td>" . $row['desc_id_1 '] . "</td>";
echo "<td>" . $row['desc_id_2'] . "</td>";
echo "</tr>";
}
echo "</table>";
Some one can help me?

You need to give each instance of table_b in your query an alias, otherwise it can't be known which one you are referring to. You also need to give the separate complete_desc values different names so they don't overwrite each other in the output array. Try something like this:
$sql="SELECT table_a.object_id, b1.complete_desc AS desc_id_1, b2.complete_desc AS desc_id_2
FROM table_a
LEFT JOIN table_b b1 ON table_a.desc_id_1 = b1.complete_desc
LEFT JOIN table_b b2 ON table_a.desc_id_2 = b2.complete_desc ";
You also need to remove the spaces in the array keys in these lines:
echo "<td>" . $row['object_id '] . "</td>";
echo "<td>" . $row['desc_id_1 '] . "</td>";
they should be:
echo "<td>" . $row['object_id'] . "</td>";
echo "<td>" . $row['desc_id_1'] . "</td>";

It is important that I urge you to restructure your "table_a" table. It just isn't set up to run clean, efficient, concise queries.
To normalize the structure, I recommend these columns:
object_id
desc_id
desc_order
Then the "pivot" query that you desire can be executed with just one LEFT JOIN.
SELECT object_id,
MAX(CASE WHEN desc_order = 1 THEN b.desc_id ELSE NULL END) AS desc_id1,
MAX(CASE WHEN desc_order = 2 THEN b.desc_id ELSE NULL END) AS desc_id2,
MAX(CASE WHEN desc_order = 3 THEN b.desc_id ELSE NULL END) AS desc_id3,
MAX(CASE WHEN desc_order = 4 THEN b.desc_id ELSE NULL END) AS desc_id4
FROM `table_a` a
LEFT JOIN `table_b` b ON a.desc_id = b.desc_id
GROUP BY `object_id`
SQLFIDDLE DEMO
I can only hope that you aren't too far in your project to make this adjustment, because it will set you up for a much easier time developing in the future. (Plus flexibility is improved -- if you decide you want more than 4 columns, you can seamlessly include 5 or more columns in the result set.

To get what you want, the JOINs need to be on the matching IDs, then get the respective description AFTER the join. If a given "ID" may not be present, you would need a LEFT-JOIN meaning all records from the LEFT side (first table/alias) regardless of a match on the right (second table/alias). Also, good to get into using aliases to simplify readability, especially on long table names, or when you need the same table multiple times such as this case...
select
a.Object_ID,
id1.complete_desc ID1Descript,
id2.complete_desc ID2Descript,
id3.complete_desc ID3Descript,
id4.complete_desc ID4Descript
from
Table_A a
LEFT JOIN Table_B id1
on a.desc_id_1 = id1.desc_id
LEFT JOIN Table_B id2
on a.desc_id_2 = id2.desc_id
LEFT JOIN Table_B id3
on a.desc_id_3 = id3.desc_id
LEFT JOIN Table_B id4
on a.desc_id_4 = id4.desc_id
Your join would never have a match such as ID Number compared to a description. You need the ID from the columns in your Table_A joined to the ID column of TableB, hence multiple "alias" references for alias "id1", "id2", "id3", "id4"...
BTW, may people frown on too many underscores for tables and/or columns. Get used to CamelCaseColumnNaming vs Using_Underscore_For_Columns. Just a suggestion...

Related

How to show in a table results based on my DataBase? Mysql PHP

I have these 3 tables in my DB:
Conductores: id_conductor, nombre_conductor
Trayectos: id_trayecto, Trayecto, Origen, Destino, Horas_conduccion
Viajes: id_viaje, id_conductor, id_trayecto, Salida, Llegada, Horas_conduccion, Disco, Semana
The table "Viajes" is the one in which I will insert the journeis of the truck drivers(conductor) every day, and I want to calculate the drive hours and rest hours for each truck driver in a table like this one:
The Code that I have to build this table is the following:
The connection to the data base obviously...
<?php
echo "<table border='1'>";
echo "<tr>";
echo "<td><b>Conductor</b></td>";
echo "<td><b>Posicion Actual</b></td>";
// (etc.........)
echo "<td><b>Descansos 11 H.</b></td>";
echo "</tr>";
$sql="SELECT * FROM conductores ";
$resultado=mysql_query($sql);
while($row=mysql_fetch_array($resultado)){
echo "<tr>";
echo "<td valign='top'>" . nl2br($row["nombre_conductor"]) . "</td>";
echo "<td></td>";
// (etc.........)
echo "</tr>";
}
I know how to calculate columns but just for one truck driver, for instance, if I want the Current Position (Posicion Actual) for driver 1, I'll do:
$result=mysql_query("SELECT Destino FROM trayectos WHERE (SELECT MAX(id_viaje) FROM viajes WHERE id_conductor=1)");
$row = mysql_fetch_array($result, MYSQL_ASSOC);
echo "Posición Actual = " . $row["Destino"];
Hours driving last week:
$result = mysql_query("SELECT SEC_TO_TIME (SUM( TIME_TO_SEC(Horas_conduccion))) as total FROM viajes WHERE id_conductor=1 AND semana=week(curdate())-1");
$row = mysql_fetch_array($result, MYSQL_ASSOC);
echo "horas semana anterior = " . $row["total"];
And so on with the rest.
So I want to do it automatically for each truck Driver, and cover the hole table.
Could you help me? I'm a little bit lost.
Get the ids of each conductor from the list of conductors and then pass it to the query and loop it.
$result=mysql_query("SELECT Destino FROM trayectos WHERE (SELECT MAX(id_viaje) FROM viajes WHERE id_conductor='.$conductor_id)");
You will need a combination of subqueries and joins to combine all these data into a single query.
SELECT c.*, t1.maxid, tr.Destino, t2.total FROM conductores c
LEFT JOIN (SELECT id_conductor, MAX(id_viaje) maxid FROM viajes GROUP BY id_conductor) t1 on c.id_conductor = t1.id_conductor
LEFT JOIN viajes v on t1.maxid=v.id_viaje
LEFT JOIN trayectos tr on tr.id_trayecto = v.id_trayecto
LEFT JOIN (SELECT id_conductor, SEC_TO_TIME (SUM( TIME_TO_SEC(Horas_conduccion))) as total
FROM viajes
GROUP BY id_conductor
WHERE semana=week(curdate())-1) t2 on c.id_conductor=t2.id_conductor
The 1st subquery retrieves the max(id_viaje) from viajes table by driver. Then I join again the viajes table to get the corresponding id_trayecto back and use that data to get the destination.
The 2nd subquery get the time summary by driver.

Print data from two different tables with a shared field (mysql and php)

I'm trying to bring data from two different tables where there is a shared field:
in table1, I have many fields and one of them is the employee Position which is a number.
in table2 I have two fields: EmpPos(which is equal to Position in table1) and PosName.
Now, I want to print all employees' info from table1 but instead of printing Position(which is a number), I want to print its associated PosName from table2.
My following query is not working!
$sql ="SELECT * FROM table1, table2 WHERE table1.Position=table2.EmpPos";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
<tr>
<th>Name</th>
<th>Email</th>
<th>Position Name</th>
<th>phoneExt</th>
</tr>";
while($row = $result->fetch_assoc()) {
echo "<tr>";
echo "<td>" .$row['table1.FirstName'] ." " .$row['table1.LastName'] ."</td>";
echo "<td>" .$row['table1.Email'] ."</td>";
echo "<td>" .$row['table2.PosName'] ."</td>";
echo "<td>" .$row['table1.phoneExt'] ."</td>";
echo"</tr>";
}
Thanks in advance
The issue is you didn't define any relationship between the tables. So you should be using INNER or LEFT JOIN for this:
SELECT * FROM Table1 m INNER JOIN
Table2 k ON k.EmpPos = m.Position
Or the following should do:
SELECT * FROM Table1 m LEFT JOIN
Table2 k ON k.EmpPos = m.Position
As you have a foreign key (Shared field), then it's easy and obvious to use joins.
Using Inner JOIN
SELECT * FROM table1 tab1 INNER JOIN table2 tab2 ON tab1.position = tab2.EmpPos

List IDs That Aren't in An Inner Join

I have a SELECT statement that provides me with a list of relevant IDs and company names that match the criteria. Here is the statement:
$result = mysqli_query($con,"SELECT a.OWNER_ID,b.ID, b.TITLE AS companyname FROM b_crm_act a INNER JOIN b_crm_company b ON a.OWNER_ID = b.ID");
while($row = mysqli_fetch_array($result))
{
echo "<tr>";
echo "<td>" . $row['ID'] . "</td>";
echo "<td>" . $row['companyname'] . "</td>";
echo "</tr>";
}
echo "</table>";
This lists all the IDs and company names. What I actually need is a list of IDs from b_crm_company that aren't in b_crm_act. I'm thinking I use NOT IN function but I've tried this and it's not listing anything.
Your help would be appreciated.
you can use LEFT JOIN on this
SELECT a.ID,
a.TITLE AS companyname
FROM b_crm_company a
LEFT JOIN b_crm_act b
ON a.ID = b.OWNER_ID // <== specify how the tables are linked
WHERE b.OWNER_ID IS NULL // <== a value of NULL when it doesn't exists
Not sure about your column names but this is how it looks like.
I don't know how efficient this is but have you tried using a NOT IN subquery?
SELECT ID,title FROM b_crm_company WHERE ID NOT IN( SELECT ID FROM b_crm_company INNER JOIN b_crm_act ON b_crm_act.OWNER_ID = b_crm_company.ID )

Get records from database in table with rowspan

I've try a lot of ways to get this table print as good as it should but I failed.
I know it's simple thing so I hope you help me with it.
Here's my code:
<?php
include('../connect.php');
$id=$_SESSION['login_user'];
$sql = "Select CourseName , Studentname from course p natural join student t";
$rs_result = mysql_query ($sql, $connection);
echo "<center>";
echo "<table>";
echo "<tr> <th>Course Name</th> <th> Students Name</th> </tr>";
// loop through results of database query, displaying them in the table
while($row = mysql_fetch_array( $rs_result )) {
// echo out the contents of each row into a table
echo "<tr>";
echo '<td>' . $row['CourseName'] . '</td>';
echo "<td rowspan=''> $row[Studentname] </td> ";
echo "</tr>";
}
echo "</table>";
echo "</center>";
?>
I want to be something like this
Course | Name | Student name |
Math101 | john, Mike |
...
Also, is the JOIN query between the two tables CORRECT or not?
The two tables are:
Course ( Course name - Course id )
Student ( Student name - Course id )
Try this query
$sql ="SELECT cor.CourseName,GROUP_CONCAT(stu.StudentName) AS StudentName
FROM course AS cor
LEFT JOIN student AS stu
ON stu.CourseId = cor.CourseId";
And change the the line in below
echo "<td rowspan=''>" . $row['Studentname'] . "</td> ";
This line:
echo "<td rowspan=''> $row[Studentname] </td> ";
You are accessing the array element improperly. Studentname should have single quotes around it like such:
echo "<td rowspan=''>" . $row['Studentname'] . "</td> ";
Also, in your query, this may work better:
$sql = "SELECT c.CourseName, s.StudentName
FROM course AS c
INNER JOIN student AS s
ON s.CourseId = c.CourseId";
Please use below format
SELECT CourseName , Studentname
FROM course
INNER JOIN student
ON course.id = student.id
Thanks
The problem is with Your rowspan attribute - You need to provide it with the exact number of rows to span through. Anyway, I think it is the collspan attribute You want to use, so e.g.
echo "<td collspan='2'> {$row['Studentname']} </td> ";
which means it will span through 2 columns, thus stundet's name will be both under the Name and Student name columns.
Is this what You were expecting?
Also I highly recommend not to use mysql_ functions but learn how to use mysqli or at least PDO.
I'm under the impression that you wanted to display a comma-separated list of names of all the students that attend each course, for each separate CourseName. In this case, you could change your SQL query to something like this:
SELECT CourseName, GROUP_CONCAT(Studentname SEPARATOR ', ') as names
FROM Course p NATURAL JOIN Student t
GROUP BY CourseName;
Hello please take a look of this answer. Dynamic rowspan while fetching records from database
I think it might be helpfull.

echo fetch_array row if they have the same name

SOLVED: thanks to everyone for the fast answers
I have 3 tables, i joined them(checked in SQL and the values are right) but the problem is that 2 of them have the same field "denumire" with different values and i need to echo them
To be clearer this code is echoing the same value but in the mysql the ID's are right:
echo "<td valign='top'>" . nl2br( $row1[`specializare`.'denumire']) . "</td>";
echo "<td valign='top'>" . nl2br( $row1[`disciplina`.'denumire']) . "</td>";
mysql tables structure:
specializare->ID_specializare, denumire
disciplina->ID_disciplina,denumire
preda->ID_specializare, ID_disciplina, etc
sql_query in php:
$sql1 = mysql_query("SELECT preda.ID_material, prof.ID_prof, prof.nume, prof.prenume, `specializare`.denumire, disciplina.denumire, preda.an_studiu, preda.semestru, preda.material
FROM `prof`
LEFT JOIN `preda` ON `prof`.ID_prof = `preda`.ID_prof
LEFT JOIN `specializare` ON `specializare`.ID_specializare= `preda`.ID_specializare
LEFT JOIN `disciplina` ON `disciplina`.ID_disciplina = `preda`.ID_disciplina
WHERE '".$_SESSION['ID_prof']."'=prof.ID_prof
ORDER BY specializare.denumire;");
When you run the SQL query, you should use an alias column name.
e.g.
SELECT t1.id as t1_id , t2.id as t2_id FROM table1 t1 , table2 t2 WHERE t2.id = t1.table_id_match
Use aliases in your query
SELECT specializare.denumire as val1, disciplina.denumire as val2 etc .....
then do
echo "<td valign='top'>" . nl2br( $row1['val1'])
You should use an alias on your tables and columns like this:
select
a.someColumnName as aCol,
b.someColumnName as bCol
from
table1 a
join table2 b
on a.tableID=b.tableID
And use the a/b (or whatever alias you set on tables) to determine which columns and how you refer to them when you bring them in (by using the as aCol) in the query.
When you select the column, you can an alias:
SELECT denumire AS specDenumire FROM specializare
Yes, here we need to understand wts happening.
In mysql,
you might have overcome the conflict by tablename.columnname but the result given by mysql would be:
denumire | denumire instead of specializare.'denumire' | disciplina.'denumire'
So, whem php stores that result in array while using mysql_fetch_assoc(). since, the key is like they are overwritten i.e
$arr['denumire'] = 1 //specializare.'denumire' will be overwritten by
$arr['denumire'] = 2 //disciplina.'denumire'.
So, thus you solve by alias

Categories