i'm learning SQL and need a little advice. This currently displays what i need it to, however i also want to echo all the other fields that don't have a match between tw.model_id and model.id. Also how would i create a list if there's multiple customer_name any suggestions greatly appreciated.
$sql = "SELECT * FROM tw
INNER JOIN model
ON model.id=tw.model_id
WHERE tw.completed = 1 AND tw.stock = 0
ORDER BY model.id";
$result = $conn->query($sql);
echo "<table cellspacing='0px' cellpadding='10px' align='center' width='100%'><tr>";
while($row = $result->fetch_assoc()) {
echo "<td width='7%' style='border:1px solid grey;'> " . $row["model_name"] . "<br />" . $row["quantity"] . "<br />";
echo $row["customer_name"] . "<br /></td>";
}
echo "</tr></table>";
It needs to be displayed like this:
|Model1 |Model2 |Model3
|10 |4 |6
|Joe Bloggs | |Jane Doe
Currently it does not display Model2 column as it doesn't have a match between model ids and no customer name.
table layout
Model
id
model_name
quantity
tw
id
model_name
customer_name
model_id
model_name matches both tables
model.id matches tw.model_id
You need an outer join. Inner joins must have matches.
This might help:
https://blog.codinghorror.com/a-visual-explanation-of-sql-joins/
Change your query to:
SELECT * FROM tw
OUTER JOIN model
ON model.id=tw.model_id
WHERE tw.completed = 1 AND tw.stock = 0
ORDER BY model.id
Outer join will do exactly what you need, i.e. " i also want to echo all the other fields that don't have a match between tw.model_id and model.id".
Related
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...
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.
I have three tables:
Campaign
Customer
Office
As in the Campaign table the customer_id the same is as ID in the Customer table,
then he must show the customer_name also in Customer table.
Now he is showing the customer id with: $row->customer_id
I now have the following
if ($result = $mysqli->query("SELECT * FROM campaign ORDER BY campaign_id"))
{
// display records if there are records to display
if ($result->num_rows > 0)
{
// display records in a table
echo "<table>";
while ($row = $result->fetch_object())
{
// set up a row for each record
echo "<tr>";
echo "<td>" . $row->campaign_name . "</td>";
echo "<td>" . $row->customer_id . "</td>";
echo "<td>" . $row->office_id . "</td>";
echo "</tr>";
}
echo "</table>";
}
}
Thanks!
It's not incredibly clear what you're asking, but maybe try this query?
SELECT c.*, cust.* FROM campaign c, customer cust WHERE c.customer_id=cust.customer_id ORDER BY c.campaign_id
Using explicit (instead of implicit) JOINs, this query can be written as this:
SELECT c.*, cust.* FROM campaign c JOIN customers cust ON c.customer_id=cust.customer_id
As a note, I usually prefer to call out column names explicitly in queries, but since you didn't post your schema, I wasn't sure the names of your columns. Possibly something like this:
SELECT c.campaign_name, cust.customer_id FROM campaign c JOIN customers cust ON c.customer_id=cust.customer_id
Ok lets say it looks like this in table users_chars i have
pos_zone
255
in table two
zone_id | name
255 | This_Area
how would i go about comparing them and showing the name row instead of the id
Ok using the method #missdefying posted I came up with this is this ok?
////Zone id to name
$zoneid=myQ(myF("SELECT t.zoneid
FROM users_chars c
INNER JOIN zone_settings t ON c.pos_zone = t.zoneid"));
$result=mysql_query("SELECT t.name
FROM users_chars uc
INNER JOIN zone_settings t ON uc.pos_zone = t.zoneid");
while($row = mysql_fetch_array($result))
{
$zonename = "";
if (($row['pos_zone'] == $zoneid)) {
$zonename = "<td>" . $row['name'] . "</td>";}
echo "<td>" . $zonename ."</td>";}
#missdefying Thank you
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.