I have two MySQLi queries that I am trying to convert to one join query. It's working in a way, but it's not working how I want it to.
I have 2 tables, tickets and replies. I'm selecting the information from the ticket query, and I'm selecting the information from the replies table which has the ticket id stored in there. So far, I'm outputting the initial ticket message and the first reply, but it repeats this for each reply this ticket has. So my current output is this:
Initial message
First reply
Initial message
Second reply
Initial message
Third reply
It outputs the initial message for each reply that this ticket has. I only want it to output the initial message once and then the replies that this ticket has. So far, I've tried a few different ways of doing this join query, but this is what I have right now:
$ticket = $db->conn->query("SELECT tickets.client, tickets.subject, tickets.message, tickets.created_at, tickets.status,
replies.reply_username, replies.reply_message, replies.reply_time
FROM tickets, replies
WHERE tickets.id = replies.ticket_id") or die(mysqli_error($db->conn));
Am I doing something wrong? Is my logic wrong in a place?
I'd also just like the add that my previous queries have had 'INNER join' and 'left join', but inner gives me the same output the I currently have.
A bit messy, but this is the code that is run after the query.
while($rows = $ticket->fetch_object()) {
if($_SESSION['ticket_username'] == $rows->client) {
$status = $rows->status;
echo '
<h3>'.$rows->subject.'</h3>
<small>Created by '.$rows->client.', '.$timeAgo->inWords($rows->created_at).'</small>
<hr>
<p>'.nl2br($rows->message).'</p>
<hr>
<small>Reply from '.$rows->reply_username.', '.$timeAgo->inWords($rows->reply_time).'</small>
<p>'.nl2br($rows->reply_message).'</p>
<hr>
';
} else {
header("Location: index");
}
if(!empty($errors) && is_array($errors)) {
foreach($errors as $error) {
echo $error;
}
}
}
You havent given much to go on, but your query seems ok (based on logic), leaving only one possible culprit.
By default PDO uses the PDO::FETCH_BOTH
as its fetch result. Meaning that it maps every column to its name and to an 'integer' column name.
You might need to use $statement->fetchAll(PDO::FETCH_ASSOC);
in your query for the output you expect.
Read more about PDOStatement::fetchAll here.
This may need some tweaking, but here's the way I would approach it:
while($rows = $ticket->fetch_object()) {
if($_SESSION['ticket_username'] == $rows->client) {
$status = $rows->status;
if($lastID != $rows->id){
echo '
<h3>'.$rows->subject.'</h3>
<small>Created by '.$rows->client.', '.$timeAgo->inWords($rows->created_at).'</small>
<hr>
<p>'.nl2br($rows->message).'</p>
<hr>';
}
$lastID = $rows->id;
echo '
<small>Reply from '.$rows->reply_username.', '.$timeAgo->inWords($rows->reply_time).'</small>
<p>'.nl2br($rows->reply_message).'</p>
<hr>';
} else {
header("Location: index");
}
if(!empty($errors) && is_array($errors)) {
foreach($errors as $error) {
echo $error;
}
}
}
What this is doing is checking to see if the currently printed ticket ID is the same as the last one it printed; if it is, don't print the initial message again. I'm not sure how your query is sorting your results, so you may need an ORDER BY ticket.id, replies.ticket_id
in there to make sure they're all grouped together.