EXPLAINATION
I have table with users and another table where stored certificates with user id's. 1 user can have multiple certificates. I need to select user once and list all of certificates by user id, but I can't achieve It correctly, selecting only 1 certificate for 1 user.
SAMPLE DATA
This very simplified sample data, for reality there are over 150 fields and 5 tables.
I have following tables:
Users
Id FirstName LastName
1 John Smith
2 Lisa Washington
Certificates
UserId CertificateName
1 Foo
1 Bar
1 Something
2 FooBar
2 Bizz
PHP looks like:
$UserID = get_current_user_id();
$GetUserId = $_GET["Id"];
if(isset($UserID)) {
$users = $con->prepare("
SELECT u.FirstName
,u.LastName
,c.CertificateName
FROM Users u
LEFT JOIN Certificates c ON u.Id = c.UserID
WHERE u.Id = '$GetUserId'
LIMIT 1
");
$users->execute();
$users->bind_result(
$FirstName,
$LastName,
$CertificateName
);
} else {
echo "There is no User ID detected, try to refresh browser.";
}
<html>
....
<?php
while ($users->fetch()) {
?>
<div class="grid-item"><?php echo $FirstName; ?></div>
<div class="grid-item"><?php echo $LastName; ?></div>
<div class="certificates"><?php echo $CertificateName; ?></div>
<?php
}
?>
OUTPUT FOR NOW
If I pass GetUserId = 1
I got results:
John Smith
Foo
DESIRED OUTPUT
It should list all of certificates for specific user.
John Smith
Foo
Bar
Something
WHAT I'VE TRIED
I've tried to use foreach
loop inside while loop, to get certificates, but in this way It didn't selected any certificates at all. Have you any ideas how can I achieve It?
This should work, you might have to change the separator in something else that you prefer.
SELECT u.FirstName,
u.LastName,
GROUP_CONCAT(c.CertificateName SEPARATOR '<br>') AS CertificateName
FROM Users u
LEFT JOIN Certificates c ON u.Id = c.UserID
WHERE u.Id = '$GetUserId'
LIMIT 1
Edit: Based on correct comment from @Matei Mihai that you should bind parameters instead of putting them in the query which is sql-injectable
$users = $con->prepare("
SELECT u.FirstName,
u.LastName,
GROUP_CONCAT(c.CertificateName SEPARATOR '<br>') AS CertificateName
FROM Users u
LEFT JOIN Certificates c ON u.Id = c.UserID
WHERE u.Id = ?
LIMIT 1
");
$users->bind_param('i',$GetUserId);
$users->execute();
Try this:
SELECT
*
FROM
Users usr
INNER JOIN
Certificates cert
ON
usr.Id = cert.UserId
WHERE
usr.Id = '1'
to get this OUTPUT-1 :
Id FirstName LastName UserId CertificateName
1 John Smith 1 Foo
1 John Smith 1 Bar
1 John Smith 1 Something
The output setup you have would output a multiple copies of John Smith, like so:
John Smith
Foo
John Smith
Bar
John Smith
Something
If what you want is
John Smith
Foo
Bar
Something
Then you need to either read your query into an array first before output:
<?php
$certArray = array();
while ($users->fetch()) {
$certArray[] = $CertificateName;
}
?>
<div class="grid-item"><?php echo $FirstName; ?></div>
<div class="grid-item"><?php echo $LastName; ?></div>
<?php
foreach($certArray as $CertificateName) {
?>
<div class="certificates"><?php echo $CertificateName; ?></div>
<?php
}
?>
Or break it up into 2 queries, which I'll leave for someone else to explain if you need it.
Something like this should work. I used structured programming and mysqli syntax, but I'm sure you can work with that.
<?php
//Assuming $con is your DB connector
$q = 'SELECT * FROM Users';
$r = mysqli_query($con, $q);
while($list = mysqli_fetch_assoc($r)) { ?>
<tr>
<td><?php echo $list['id']; ?></td>
<td><?php echo $list['FirstName']; ?></td>
<td><?php echo $list['LastName']; ?></td>
<td>
<?php
//echo the certificate names
$userId = $list['id'];
$q1 = 'SELECT * from Certificates WHERE UserId = '.$userId.'';
$r1 = mysqli_query($con, $q1);
while($certif = mysqli_fetch_assoc($r1)){
echo $certif['CertificateName'].'<br /> ';
}
?>
</td>
</tr>
<?php }?>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.