I am selecting data from 3 tables using a two left joins.
This all works up until the iteration of one of the values for an association (i think, through process of elimination).
I now have reason to believe the select statement is incorrect at the point of the JOINs, but i cannot see how.
The join that is not functioning as expected:
LEFT JOIN
ae_template_pageTypes t ON t.ae_template_pageTypes_id = tp.ae_template_page_group_id
Here i am trying to get the ae_template_pageTypes_type_label by the ae_template_pageTypes_idassociation.
Table: ae_template_pages
Table: ae_template_pageTypes
Table: ae_template_groups
The HTML Output(Both showing HTML instead of using join respectively)
THE ISSUE
I am expecting 2 different values in the format section where here shows both as HTML. I cannot locate why this is happening.
The SELECT
SELECT tg.ae_template_group_name, tp.ae_template_page_id, tp.ae_template_page_group_id, tp.ae_template_page_title, tp.ae_template_page_type, tp.is_group_index, t.ae_template_pageTypes_id, t.ae_template_pageTypes_type_label
FROM
ae_template_pages tp
LEFT JOIN
ae_template_pageTypes t ON t.ae_template_pageTypes_id = tp.ae_template_page_group_id
LEFT JOIN
ae_template_groups tg ON tg.ae_template_group_id = tp.ae_template_page_group_id
WHERE tp.ae_template_page_group_id = '$tempGroup_id'
NOTE: I have tried all types of join to test without finding a solution.
The PHP
foreach ($template_pages as $key => $value) {
?>
<li class="dd-item dd3-item" data-id="<? echo $template_pages[$key]['ae_template_page_id']; ?>">
<div class="dd-handle dd3-handle"></div>
<div class="dd3-content ae_template_page" data-template_page_name='<? echo $template_pages[$key]['ae_template_page_title']; ?>' data-template_page_id='<? echo $template_pages[$key]['ae_template_page_id']; ?>'><? echo $template_pages[$key]['ae_template_page_title']; ?>
<span style='float: right;margin-top: -3px;'>
<div style="" class="btn-group">
<span class="btn-info btn-xs dropdown-toggle" data-toggle="dropdown" title="Click to change file type" type="button"><? echo $template_pages[$key]['ae_template_pageTypes_type_label']; ?></span>
<ul role="menu" class="dropdown-menu" data-page_id='<? echo $template_pages[$key]['ae_template_page_id']; ?>'>
<li>JS</li>
<li>HTML</li>
<li>CSS</li>
</ul>
<span class="btn-info btn-xs" title="This file belongs to Template Group: <? echo $template_pages[$key]['ae_template_group_name']; ?>" type="button"><? echo $template_pages[$key]['ae_template_group_name']; ?></span>
<?
if ($template_pages[$key]['is_group_index'] == 1) {
?>
<span class="btn-success btn-xs" title="This is the default file for this group" type="button">Group index</span>
<?
}
?>
</div>
</span>
</div>
</li>
<?
}
SQL workbench output using the above statement with the $tempGroupId set to 1
For this and future try and restructure your sql to make it clearer eg:
select * from (
(select * from table_a) tbla
left join
(select * from table_b) tblb
on tbla.commoncolname=tblb.commoncolname
)
Try this on the database tool first (eg SQL Workbench), then move on to what the php retrieves and so on to the html
Related
I am trying to set a sql query that will show jobs from a selected type of trade and within certain distance. I have three tables clients, traders and jobs. What I need is like-
SELECT * from jobs WHERE the type of job required matches by the type of jobs this trader offers AND the DISTANCE between the client and trader is within a range specified
I have managed to get the first part done. it shows all jobs that match the types of job a trader offers, but struggling to get the second part. Here is my query
$stmt=$pdo->prepare("SELECT jobs.*, clientPostcode, traderPostcode FROM jobs
INNER JOIN traders ON FIND_IN_SET(jobs.tradeType,traders.tradeTypes ) WHERE traders.traderEmail=:traderEmail
INNER JOIN clients ON jobs.clientEmail= clients.clientEmail" );
$stmt->bindparam('traderEmail',$traderEmail);
$stmt->execute();
while($row=$stmt->fetch(PDO::FETCH_ASSOC)){
//calculate distance between origin and destination
IF (condition is ok){
?>
<div class="card col-lg-12 mt-5 text-center">
<div class="card-body">
<h6 class="card-title text-primary">Job Type: <?php echo $row['tradeType'] ?> (Job Title: <?php echo $row['jobTitle'] ?> ) </h6>
<p class="card-text"><?php echo $row['jobDescription'] ?></p>
<a class="btn btn-primary" href="">
<i class="fas fa-edit fa-xs"></i> Send Interest</a>
<a class="btn btn-success" href="" target="_blank">
<i class="fas fa-glasses fa-xs"></i> Shortlist</a>
</div>
</div>
<?php
}
}
?>
$stmt=$pdo->prepare("SELECT jobs.*, clients.clientPostcode, traders.traderPostcode FROM jobs
INNER JOIN traders ON FIND_IN_SET(jobs.tradeType,traders.tradeTypes )
INNER JOIN clients ON jobs.clientEmail= clients.clientEmail WHERE traders.traderEmail=:traderEmail " );
$stmt->bindparam('traderEmail',$traderEmail);
$stmt->execute();
while($row=$stmt->fetch(PDO::FETCH_ASSOC)){
$origin = $row['traderPostcode'];
$destination = $row['clientPostcode'];
then I used google distance matrix api (cURL)to calculate distance between the two postcodes. I appreciate everyone for your time. Will try to be more specific for future questions.
Solved!!
Thanks, guys. This was my first question on here. Let me know if I'm not formatting this correctly or something. Here's my finished code:
Answer:
$sql = 'SELECT a.*, GROUP_CONCAT(t.name) as track_name FROM albums AS a LEFT JOIN tracks AS t ON a.album_id = t.album_id GROUP BY a.album_id';
foreach ($conn->query($sql) as $row) { ?>
<div class="container">
<div class="row">
<div class="col-6">
<img src="../images/<?= $row['album_cover']?>" alt="Card image cap" style="width:100%;">
<!--shadow-->
<div class="shadow-lg p-3 mb-5 bg-white rounded">
<div class="card-body" style="padding-left:10px;">
<h4 class="card-title"><?= $row['album_name'] ?></h4>
<b><?= print_r($row['album_name'] . ' (' . $row['record_label'] . ') (' . $row['year_released'] . ')', true); ?><br><br></b>
<ul class="list-group list-group-flush">
<?php
$tracks = explode(",", $row['track_name']);
$numTracks = count($tracks);
$i = 0;
while ($i < $numTracks) { ?>
<li class="list-group-item">
<?php
echo $tracks[$i];
$i++;
?>
</li>
<?php } ?>
</ul>
</div>
</div>
</div>
</div>
</div>
<?php } ?>
Question (Solved): I am working on a project for school. I have to revamp an existing discography site (Queen) using php. The part I'm stuck on now is pulling album info from a database and using it to populate the page with each album along with the track names for the album. I have my album info in one table called albums, and all the tracks for every album in another table called tracks, with album_id as a foreign key.
I can get to the point where it's generating the album title from the album table in my database, but I have no idea how to get the tracks for each album.
This is my SQL query:
$sql = '
SELECT a.album_id
, a.album_name
, a.year_released
, a.record_label
, a.album_cover
, t.name
, t.album_id
FROM albums AS a
LEFT
JOIN tracks AS t
USING (album_id)
';
And here is the part in that is supposed to generate the albums:
<?php
foreach ($conn->query($sql) as $row) { ?>
<div class="col-6">
<img src="../images/<?= $row['album_cover']?>" alt="Card image cap" style="width:100%;">
<!--shadow-->
<div class="shadow-lg p-3 mb-5 bg-white rounded">
<div class="card-body" style="padding-left:10px;">
<h4 class="card-title"><?= $row['album_name'] ?></h4>
<b><?= print_r($row['album_name'] . ' (' . $row['record_label'] . ') (' . $row['year_released'] . ')', true); ?><br><br></b>
<ul class="list-group list-group-flush">
<li class="list-group-item">Innuendo</li> <!-- these are just placeholders for the tracks because I don't know what to do here! -->
<li class="list-group-item">I'm Going Slightly Mad </li>
<li class="list-group-item">Headlong</li>
<li class="list-group-item">I Can't Live With You</li>
<li class="list-group-item">Don't Try So Hard </li>
<li class="list-group-item">Ride The Wild Wind</li>
<li class="list-group-item">All God's People</li>
<li class="list-group-item">These Are The Days Of Our Lives</li>
<li class="list-group-item">Delilah</li>
<li class="list-group-item">The Hitman</li>
<li class="list-group-item">Bijou</li>
<li class="list-group-item">The Show Must Go On </li>
</ul>
</div>
</div>
</div>
<?php
}
?>
As it stands, my page is being populated by the same album info over and over because the foreach is iterating through every row in both tables. How do I generate specific tracks based on unique albums?
Try using ON instead of USING:
$sql = 'SELECT * FROM albums AS a LEFT JOIN tracks AS t ON a.album_id = t.album_id';
This should join the two tables correctly. If there are multiple tracks for each album you will need to either query them separately or join the tracks into a group using GROUP_CONCAT. Here would be the query to accomplish this:
$sql = 'SELECT a.*, GROUP_CONCAT(t.name) as track_name FROM albums AS a LEFT JOIN tracks AS t ON a.album_id = t.album_id GROUP BY a.album_id';
Just as a side note I HIGHLY recommend using PDO for all sql related things. Here is a link to set it up and use it for safer sql queries: https://www.w3resource.com/php/pdo/php-pdo.php
ADDED TO LOOP THROUGH TRACKS
First you would need to take the variable and explode it into an array (place inside your loop):
$tracks = explode(',',$row['track_name']);
foreach($tracks as $track_name){
echo $track_name;
}
Now you should be able to do anything you want with these tracks. You could easily place them in a table or in a div.
You call $conn->query($sql) every loop which will return the whole result set again. Also, use while loop like below, not foreach loop since $conn->query() return a mysqli_reuslt object, not an array.
$sql = 'SELECT a.album_id, a.album_name, a.year_released, a.record_label, a.album_cover, t.name, t.album_id
FROM albums AS a LEFT JOIN tracks AS t USING (album_id)';
$result = $conn->query($sql) // return a mysqli_result object
while($row = $result->fetch_assoc()) {
// Your loop content
}
If you insist on using foreach loop:
$result = $conn->query($sql) // return a mysqli_result object
$rows=$result->fetch_all(MYSQLI_ASSOC); //return an array
foreach($rows as $row) {
//content
}
Two ways in which you could approach this problem:
Have 2 loops - the first looping through a simple query to the albums table (no joins), then within that loop perform a second query to the database to get all the tracks. (The downside being that you will be making more queries to the database)
Alternatively, change your query so you are selecting from the tracks table and then the join is on the albums table. To have it so the album title is only printed once for each album, you would need to sort the tracks by album, and then have an if statement to check when the loop has started processing a different album.
You must change your design a little.
First you get the first row get the album data and the first track
After that you grap the rest of the track and close the html tags
$sql = 'SELECT a.album_id, a.album_name, a.year_released, a.record_label
,a.album_cover, t.name, t.album_id
FROM albums AS a LEFT JOIN tracks AS t USING (album_id)';
$result = $conn->query($sql) // get a result from the mysql server
$row = $result->fetch_assoc();
?>
<div class="col-6">
<img src="../images/<?= $row['album_cover']?>" alt="Card image cap" style="width:100%;">
<!--shadow-->
<div class="shadow-lg p-3 mb-5 bg-white rounded">
<div class="card-body" style="padding-left:10px;">
<h4 class="card-title"><?= $row['album_name'] ?></h4>
<b><?= print_r($row['album_name'] . ' (' . $row['record_label'] .
') (' . $row['year_released'] . ')', true); ?><br><br></b>
<ul class="list-group list-group-flush">
<li class="list-group-item"><?= $row['name']?></li>
<?php
//get the rest of teh tracks
while($row = $result->fetch_assoc()) {?>
<li class="list-group-item"><?= $row['name']?></li>
<?php
} //end if While
?>
</ul>
</div>
</div>
</div>
I am making a system and I need to see information for each student. When I click the button, I need to know the student's code and open a page (seeStudent.php) with the student's information. Can someone help me?
<?php
$sql = $conn->query("SELECT * from tb_coordinator inner join tb_teacher
on tb_coordinator.cd_coord = tb_teacher.cd_coord
inner join teacher_class on
tb_teacher.cd_teacher = teacher_class.cd_teacher
inner join tb_teacher on
teacher_class.cd_class = tb_class.cd_class
inner join tb_student on
tb_class.cd_class = tb_student.cd_class
where tb_teacher.cd_cpf = '$cpf' and nm_class = '3a1' order by cd_number asc");
while($row = mysqli_fetch_array($sql)){
$nm_student = $row['nm_student'];
$cd_number = $row['cd_number'];
?>
<ul class="list-group list-group-flush" style="width: 50%; margin-top: 2%;">
<div id="load_student">
<li class="list-group-item"><?php echo $cd_number . " - " . $nm_student;?>
Get Information</button></li>
</div>
</ul>
</div>
<?php }?>
You need a bit modification in your prepared HTML. Add your required parameters to the anchor href which might help you to get student details from database in seeStudent.php page.
<ul class="list-group list-group-flush" style="width: 50%; margin-top: 2%;">
<div id="load_student">
<li class="list-group-item"><?php echo $cd_number . " - " . $nm_student;?>
<a href="seeStudent.php?cd_number=<?=$cd_number?>&nm_student=<?=$nm_student?>" >
<button type="button" class="btn btn-outline-info" style="margin-left: 90%;">Get Information</button>
</a>
</li>
</div>
</ul>
If you click Get Information button, it will be taken you to seeStudent.php with two $_GET parameters (cd_number, nm_student).
Now the final task. In seeStudent.php page take the parameter from $_GET array and do other query to get student details from database and to display.
seeStudent.php
<?php
$cd_number = isset($_GET['cd_number']) ? $_GET['cd_number'] : '';
$nm_student= isset($_GET['nm_student']) ? $_GET['nm_student'] : '';
// .... code stuff, possibly query and display
?>
Hey there guys/girls I have an issue I'm currently trying to work through being a novice to MYSQL / PHP. Currently I'm using Bootstrap accordion collapsible components to display HTML tables (That are reports). Here is my current table:
Current Table in MYSQL.
So as you can see the reports row contains some HTML information which are tables. I wanted to take the information and display it on a webpage assuming that every row was a different report. So I was able to do so with writing this:
<div class="accordion" id="accordionExample">
<?php
require('db.php');
$i = 0;
$sql = "SELECT `report` FROM `automation-reports`;";
$query = mysqli_query($connection, $sql);
while($row = mysqli_fetch_assoc($query))
{
foreach($row as $key => $value)
{
?>
<div class="card">
<div class="card-header" id="heading<?php echo $i ?>">
<h5 class="mb-0">
<button class="btn btn-link" type="button" data-toggle="collapse" data-target="#collapse<?php echo $i ?>" aria-expanded="true" aria-controls="collapse<?php echo $i ?>">
Report #1: 8/6/2018
</button>
</h5>
</div>
<div id="collapse<?php echo $i ?>" class="collapse" aria-labelledby="heading<?php echo $i ?>" data-parent="#accordionExample">
<div style="text-align: center;" class="card-body">
<h3 style="float: left;"> Rating-Pull: </h3>
<?php
$i++;
echo $key;
echo "$value";
?>
</div>
</div>
</div>
<?php
}
}
?>
</div>
Which is great because it does what I thought I wanted it to do , which is this:
Display Output
What's not so great is now I realize that multiple reports are going to be in one accordion "folder" which is where the reportid row comes into play. So lets say I run my program and two (different) reports run on it but I want it in the say "folder" on the webpage. Both of these get labeled with a reportid of 1.
So what I want to do is loop through reports and then if they have the same ID group them together in that folder and iterate through the whole table like that. So that's the part where I have attempted to do so with a nested loop and SELECT 'report' FROM 'automation-reports' WHERE 'reportid' = '$i' ; and I just ended up getting the first element. Could somebody give me a hand with this and a good explanation so I can understand and learn what's happening?
Thank you!
EDIT:
Maybe a visual would be better?
VISUAL
I think GROUP BY and GROUP_CONCAT are what you are looking for.
SELECT `reportid`, GROUP_CONCAT(`report` SEPARATOR '') as report
FROM `automation-reports`
GROUP BY `reportid`
shoud do the job.
SELECT *
FROM `automation-reports`
GROUP BY `reportid`
will give you one row for each id ie.
id 1,
id 2,
id 3
Or do you want to display each row like so?
id 1, id 1,
id 2,
id 3, id 3,
id 4
if so here is a possible example of combining the reports in a loop first
$sql = "SELECT reportid, GROUP_CONCAT(report SEPARATOR ',') as reports FROM `automation-reports` GROUP BY `reportid`;";
while($row = mysqli_fetch_assoc($query)) {
echo "<div id='{$row['reportid']}'>";
echo $row['reports'];
echo "</div>";
}
I know this isn't the HTML you're after but you should be able to place your HTML in this code
I'm making a PHP SQL db to catalog short stories. On my index page that shows little excerpts of the stories, I'm trying to display the sql rows from a table (stories) as an unordered list using the while looping function. Ratings for the stories are held in another table and I'm linking it to the 'stories' table using LEFT JOIN and the unique column rows "id" and 'storyid'.
Upon loading, the data displays just fine, however only one SQL row is showing, and my limit is set to 50. The while loop script and sql(close) script flank the list item. No error messages are reporting.
can anyone suggest why only 1 item is showing?
<?php
include("db.php");
$query="SELECT s.*, AVG(r.rank) AS avrank
FROM (SELECT *
FROM stories
WHERE id BETWEEN 1 AND 100
ORDER BY RAND()
LIMIT 50) AS s
LEFT JOIN ratings AS r ON r.storyidr = s.id";
$result=mysqli_query($connection,$query);
?>
<ul id="tiles">
<?php
while ($data = mysqli_fetch_assoc($result)):
$id = $data['id'];
$author = $data['author'];
$page_path = $data['page_path'];
$title = $data['title'];
$avgrate = $data['avrank'];
if(is_null($page_path)){$page_path = "#";}
?>
<li>
<div class="post-info">
<h3><?php echo $title; ?></h3>
<h3>rating is <?php echo $avgrate; ?>/5</h3>
<span><a href="categories/<?php echo $category; ?>.php">
<label> </label>
</span> </div>
<div class="post-info-rate-share">
<form method="POST" action="rating.php?id=<?php echo $id; ?>">
<fieldset class="rating">
<legend> Rating: <?php echo $avgrate=round($avgrate,2); ?>/5</legend>
<input type="radio" id="star5" name="starno" value="5" onclick="this.form.submit()"/>
</fieldset>
</form>
</div>
</li>
<?php
endwhile;
mysqli_close($connection);
?>
</ul>
You missed the GROUP BY:
SELECT s.*, AVG(r.rank) AS avrank
FROM stories s
LEFT JOIN ratings AS r ON r.storyidr = s.id
WHERE id BETWEEN 1 AND 100
GROUP BY s.id
ORDER BY RAND()
LIMIT 50;
Demo: http://sqlfiddle.com/#!2/7a9fa/9