PHP and sql diplay item - php

I'm facing some problem regarding to display data from sql.
I store my data into 2 table: table student and table company.
table student
{ id, name, company_code, fac_staff_id }
table company
{id, company_name, company_state}
I'm trying to create a table shown as below.
State A
company A
student 1
student 2
company B
student 3
student 4
State B
company C
student 5
company D
student 6
student 7
student 8
I tried create a table similar as above structure but just want classify all the student based on there company_state. The output just display only one state and put all student into that state.
$querysel = "SELECT DISTINCT c.company_state,s.fac_staff_id FROM tblcompany
c, tblstudent s WHERE c.id = s.company_code " ;
$resultsel = mysql_query($querysel, $connection);
$querystdsel = "SELECT s.name,c.company_state FROM tblcompany c,
tblstudent s WHERE c.id = s.company_code " ;
$resultstdsel = mysql_query($querystdsel, $connection);
while($rowsel =mysql_fetch_array($resultsel)){
if ($rowsel['fac_staff_id'] == NULL){
echo $rowsel['company_state'];
while($rowstdsel =mysql_fetch_array($resultstdsel)){
if($rowstdsel['company_state']=$rowsel['company_state']){
echo $rowstdsel['name'];
}
}
}
}
Hope someone can tell me way to create a table like above or any alternative ways because i'm still poor in php and mysql. thank you

You should join your statements to have only one result, where every row looks like this with "order by company_state, company_name"
state | company | student
A | A | student1
A | A | student2
A | B | student3
....
In your php you then use lists to get your structure. Something like this: Just written down and no nice, clean, functional code!
<?php
$rows = mysqli_fetch_array($result);
echo "<ul>";
$lastcompany = "";
$laststate = "";
foreach($rows as $row)
{
if(($laststate == "") or ($laststate != $row['state']))
{
// New Item on mainlist: states
if($laststate != $row['state'])
{ // close previous lists (students, companies)
echo "</ul></ul></li>";
}
echo "<li>".$row['state'];
}
if(($lastcompany == "") or ($lastcompany != $row['company']))
{
// New Item on mainlist: companies
if($lastcompany != $row['company'])
{ // close previous (students) list
echo "</ul></li>";
}
echo "<li>".$row['company'];
}
// New student entry
echo "<li>".$row['company']."</li>";
// Redmine company and state for next iteration
$lastcompany = $row['company'];
$laststate = $row['state'];
}
// After all close all lists
echo "</ul></ul></ul>";
?>

Related

Best practice for writing code in php for foreach->foreach->if(1st loop id == 2nd loop id)->result

First loop table
user_id | fname | lname
1 | first | emp
2 | second| emp
3 | third | emp
Second loop table
shift_id | employee_id
1 | 1
2 | 2
3 | 2
if($employees)
{
foreach ($employees as $employee)
{
if($employee['user_id'] == $shift['employee_id'])
{
echo ucwords($employee['fname']. ' ' .$employee['lname']);
}
}
}
I am getting the right result but I think there is some better way of writing this.
You can use joins in table. Left join means that the user line has to exists (because: LEFT) and the shifts enty is optional.
SELECT user.user_id, user.fname, user.lname, shifts.shift_id
FROM yourUserTable AS user
LEFT JOIN yourShiftsTable AS shifts ON(user.user_id = shifts.employee_id)
Now you get it in your initial array, as if you'd select it as one row from a table and no longer need to do tricks in PHP to combine information. If you can, always try to get the database to manage data, it does that way faster than PHP can.
Please note, the query could be a little off, I just wrote this out of the top of my head.
Just some test code I whipped up to test this from the information provided for this "Demonstration Code".
Note: I have used the mysqli class for the database (instantiating $db ) and have excluded the SQL Table setup.
What you would have had is something along the lines of this...
Case 1 - The original
$db = new mysqli('localhost', 'root', 'test', 'phptutorials_st26');
echo '<h2>Create $employees </h2>';
$query = "SELECT * FROM users";
$result = $db->query($query);
$employees = $result->fetch_all(MYSQL_ASSOC);
var_dump($employees);
echo '<h2>Create $shifts </h2>';
$query = "SELECT * FROM shifts";
$result = $db->query($query);
$shifts = $result->fetch_all(MYSQL_ASSOC);
var_dump($shifts);
echo '<h2>Using foreach on $employees and $shifts</h2>';
if ($employees) {
foreach ($employees as $employee) {
foreach ($shifts as $shift) {
if ($employee['user_id'] == $shift['employee_id']) {
echo ucwords($employee['fname'] . ' ' . $employee['lname']);
echo '<br>';
}
}
}
}
The Result from the above is
First Emp
Second Emp
Second Emp
Case 2 - Using a Join
Well using a join, as everyone has already stated, is the way to go...
$sql = "SELECT u.user_id, u.fname, u.lname, s.shift_id
FROM users AS u
JOIN shifts AS s ON(u.user_id = s.employee_id)
";
$result = $db->query($sql);
$employees = $result->fetch_all(MYSQL_ASSOC);
// To see what comes out because we always check things.
var_dump($joined_result);
(Don't ask me why I love using very abbreviated aliases for the table names! It's just "a thing".)
Then your "loop" simply becomes...
echo '<h2>Using foreach on join</h2>';
foreach ($employees as $employee) {
echo ucwords($employee['fname'] . ' ' . $employee['lname']);
echo '<br>';
}
And the result is...
First Emp
Second Emp
Second Emp
Case 2 - has reduced the code and only requires 1 Trip to the Database.
Does that help you any?
You could do it this way also. Its a little shorter.
SELECT TABLE1.FNAME, TABLE1.LNAME, TABLE2.EMPLOYEE_ID
FROM TABLE1, TABLE2
WHERE TABLE1.USER_ID = TABLE2.EMPLOYEE_ID;

foreach for discinct value and multiple result on the same line

In a nutshell:
I want to create a list for students and grades. When I get my sql, I get many grades for the same student. What I'm trying to do is this:
Student 1 -> Grade 1 -> Grade 1 -> Grade 3
Student 2 -> Grade 1 -> Grade 2 -> Grade 3
My sql pulls all the records in the database which is great but how can I get it to display like this?
SQL is very standard
$query_getGradesTr1 = "SELECT gradeID, studentID, grades.examID, grade FROM grades, exams WHERE exams.trackID=1 AND grades.examID=exams.examID";
$getGradesTr1 = mysql_query($query_getGradesTr1, $Site) or die(mysql_error());
$row_getGradesTr1 = mysql_fetch_assoc($getGradesTr1);
$totalRows_getGradesTr1 = mysql_num_rows($getGradesTr1);
I thought about using a foreach to go through the results, basically foreach studentID give me all the grades associated with them and repeat for each students... But I get multiple results with same StudentID then another studentID, like this:
Student 1 -> Grade 1
Student 1 -> Grade 2
Student 1 -> Grade 3
Student 2 -> Grade 1
Student 2 -> Grade 2
Student 2 -> Grade 3
Any suggestions??
Do this:
$current_student = NULL;
foreach($totalRows_getGradesTr1 as $each) {
// Check here is student does not matches to previous student
if($each->studentID !== $current_student) {
// If not matches then print, else ignore
echo "$each->studentID";
}
// Assign to check again in next loop
$current_student = $each->studentID;
// Always print grade
echo "-> $each->gradeID";
}
Another solution is, twice loop the array and make each studentId as array key assign all grades to the studentID, like:
$students_grades = array();
foreach($totalRows_getGradesTr1 as $each) {
if(!isset($student_grades[$each->studentID]) {
$student_grades[$each->studentID] = array();
}
$student_grades[$each->studentID][] = $each->gradeID;
}
// Then nested loop here and print records
foreach($student_grades as $studentID => $grades) {
echo "$studentID -> " . implode('->', $grades) . "\r<br>";
}

Working with 2 tables PHP & MySQL

I am working on a webpage that displays list of shops. I have 2 tables, shops and shops_sched.
+-shops-+
| id | title |
+-------------shops_sched-------------+
| id | shops_id | start_date | end_date |
Basically, the program displays the list of shops from the shops table, but if a value from shops.id is found # shops_sched.shops_id the page must output shops.title + 'coming soon'.
I understand this will be easy if I just place the date fields inside the table shops but due to programming restrictions I can't. I'm working on an existing project and I'm trying to minimize changes to existing functions. I can create new PHP functions if necessary though.
In addition, I need to get all the entries from the shops table. The Program needs to return all shops.title but for those shops whose id is found # shops_sched.shops_id, the program will have to return shops.title + "Coming Soon".
must output shops.title + 'coming soon'.
So do it like this:
$shops.title = "Donut-John";
echo $shops.title." coming soon";
To join the shops and shops_sched table
$query = SELECT `title` FROM `shops` JOIN `shops_sched` ON `shops`.`id` = `shops_sched`.`shops_id` WHERE `shops_sched`.`shop_id` = 5;
$result = mysql_query($query);
while($row = mysql_fetch_array($result) {
echo $row['title'] . 'coming soon';
}
For more about join you also can refer the following link
https://dev.mysql.com/doc/refman/5.0/en/join.html
http://www.tutorialspoint.com/mysql/mysql-using-joins.htm
Join the two tables :
SELECT shops.title
FROM shops INNER JOIN shops_sched ON shops.id = shops_sched.shops_id
The query should return only the the shops inside shops_sched
EDIT :
If I understood your question, try this :
SELECT shops.title, shops_sched.id
FROM shops LEFT JOIN shops_sched ON shops.id = shops_sched.shops_id
This will return all the titles, and the shops_sched.shops_id if shops.id = shops_sched.shops_id. In the other case, the hops_sched.shops_id will be null
Then you fetch the rows and if the second row is not null, print title + coming soon
Sample code : (Something like this)
$query = "SELECT `title`, 'shops_id' FROM `shops` LEFT JOIN `shops_sched` ON `shops`.`id` = `shops_sched`.`shops_id` WHERE `shops_sched`.`shop_id`";
$result = mysql_query($query);
while($row = mysql_fetch_array($result) {
if($row['shops_id'] != "")
{
echo $row['title'] . ' coming soon';
}
else
{
echo $row['title'];
}
}

PHP/MYSQL: how to loop matching results from a query already inside a while loop

I'm very new to PHP/MYSQL and find this quite difficult to explain, so hopefully someone will understand what I'm trying to do. I have a database that collects information on artists and songs. I want to be able to link the artists to the song and display the "credit" with the song information.
I have a database with tables similar to this:
Artist
| artist_id, artist_name
Credits
| credit_id, credit_name
Song
| song_id, song_name
Credit_To_Artist
| credit_id, artist_id, song_id
Example data:
Artist
| 2, Peter Mark
Artist
| 5, Mette Christiansen
Credits
| 1, Producer
Credits
| 2, Writer
Credits
| 3, Vocalist
Song
| 23, The Game
Credit_To_Artist
| 1, 2, 23
Credit_To_Artist
| 2, 2, 23
Credit_To_Artist
| 3, 5, 23
I have created a page "song.php" that displays information on each song using mysql_real_escape_string to get the song ID from the URL:
$id = mysql_real_escape_string($_GET['id']);
if (!$id) {
die('Please provide an id!');
}
$query = "SELECT * FROM `Credit_To_Artist` AS c2a
INNER JOIN `Credits` AS cr ON cr.credit_id = c2a.credit_id
LEFT OUTER JOIN `Artist` AS a ON a.artist_id = c2a.artist_id
LEFT OUTER JOIN `Song` AS s ON s.song_id = c2a.song_id
WHERE c2a.song_id = $id";
$res = mysql_query($query);
$row = mysql_fetch_assoc($res);
The issue I'm having is I want to be able to list all of the artists linked to that song, and all of their credits in brackets next to it. Since there are more than one artist linked to each song, and most of them have more than one credit (producer, writer, vocalist etc), I have no idea how to write a loop function that shows both of these. Below is my attempt to show what I mean, although it obviously doesn't work:
while ($row = mysql_fetch_array($res)) {
$artist = $row[artist_name];
echo "$artist";
while ($row = mysql_fetch_array($res)) {
$credit = $row[credit_name];
echo "$credit";
}
echo "<br />";
}
This is what I'd ideally like to achieve from the example data above:
Song: The Game
Credits: Peter Mark (Producer, Writer)
Mette Christiansen (Vocalist)
You have two options:
GROUP_CONCAT(..)
You can use GROUP_CONCAT(..). This mysql function groups values in a column that are in each group. You would alter the sql to group by artist_id in this case.
SELECT a.artist_name as aname, GROUP_CONCAT(c.credit_name) as credits
FROM Credits_To_Artist as c2a
JOIN Artist as a ON c2a.artist_id = a.artist_id
JOIN Credits as c ON c2a.credit_id = c.credit_id
GROUP BY c2a.credit_id
Your rows would look like:
Array( "aname" => "name",
"credits" => "function 1,function 2" )
The biggest problem with GROUP_CONCAT is that if you have to concat a lot of values together, it might exceed the maximum width of the row. This does not seem to be the case for your problem. You would not need a loop with this approach.
Adding to array
If you keep the query as it is, you have a row for each 'credit'. You can prepare your data by adding it to an Array, then use implode(..) in php to add commas.
$artists = Array();
while( $row = mysql_fetch_array($res) ) {
$artist = $row[artist_name];
$credit = $row[credit_name];
if( !array_key_exists( $artist, $artists ) ) {
$artists[$artist] = Array();
}
$artists[$artist][] = $credit;
}
foreach( $artists as $artist => $creditarr ) {
$credits = implode( ", ", $creditarr );
echo "{$artist} ({$credits})<br>";
}
You'll find that preparing your data in an array will sometimes be much faster than writing a query that does the same thing. I would probably choose the latter solution.
Let's start with the tables, here is what i think you should do
artist | id, name
song | id, title
credit | id, credit
song_artists | id, song_id, artist_id
credit_to_artists | id, song_artists_id, credit_id
Should be the way to handle the kind of relationship you want.
And here is the PHP code, it might not be the most efficient one, but it will do the job
$query = "SELECT * FROM song_artists WHERE song_id = $id_from_link";
$result = mysql_query($query);
while($row = mysql_fetch_array($result))
{
$artistQuery = "SELECT * from artist WHERE id = {$row['artist_id']}";
$artistResult = mysql_query($artistQuery);
while($artistRow = mysql_fetch_array($artistResult))
{
echo "The Artist: " . $artistRow['name'];
}
echo $songArtistId;
$creditToArtistQuery = "SELECT * FROM credit_to_artists WHERE song_artists_id = {$row['id']}";
$creditToArtistResult = mysql_query($creditToArtistQuery);
if(mysql_num_rows($creditToArtistResult)>0)
{
echo " { ";
$isFirstCredit = true;
while($creditToArtistRow = mysql_fetch_array($creditToArtistResult))
{
$creditQuery = "SELECT * FROM credit WHERE id = {$creditToArtistRow['credit_id']}";
$creditResult = mysql_query($creditQuery);
while($creditRow = mysql_fetch_array($creditResult))
{
if($isFirstCredit)
{
echo $creditRow['credit'];
$isFirstCredit = false;
}
else
{
echo ", " .$creditRow['credit'];
}
}
}
echo " } <br />";
}
}

Join of 3 Tables - How to walk through results?

I have this sql statement joining 3 tables:
SELECT * FROM `int_news`
LEFT JOIN tl_member ON int_news.member_id = tl_member.id
LEFT JOIN tl_news ON int_news.news_id = tl_news.id
The 3 Tables are like this:
Table 1 (int_news)
ID, member_id, news_id
Table 2 (tl_member)
id, firstname, lastname
Table 3 (tl_news)
id, headline
So far so good, but it seems i have a big blackhole in my head making me unable to solve how to output the result like this
For each "headline" i want ALL lastnames e.g.
headline 1 Jonny
Walker
Jim
headline 2 Knopf
Jon
Doe
It sounds your looking something like a pivot so if you group your query by headline, it will display each lastname as a column.
I found this good tutorial on pivots for mysql that might help you http://www.artfulsoftware.com/infotree/queries.php#78
headline 1 Jonny Walker Jim
headline 2 Knopf Jon Doe
Here is a loop that would do that *Forgive my php it's been a while.
$curHeadline = "";
while ( $db_field = mysql_fetch_assoc($result) ) {
if($curHeadline != $db_field['headline'])
{
$curHeadline = $db_field['headline'];
print $curHeadline . $db_field['ID']
}
print $db_field['lastName'] . "<BR>";
}
Try this for mysql :
SELECT tlnews.headline, GROUP_CONCAT(tl_member.last_name)
FROM `int_news` LEFT JOIN tl_member ON int_news.member_id = tl_member.id
LEFT JOIN tl_news ON int_news.news_id = tl_news.id
GROUP BY 1;
Expected Output:
headline1 Johnny,Walker,Jim
headline2 Knopf,Jon,Doe
...
Would something like this vaguely reflect your situation?
<?php
$sql = "
SELECT
`int_news`.`ID` AS `int_news_ID`,
`int_news`.`member_id`,
`int_news`.`news_id`,
`t1_member`.`id` AS `t1_member_id`,
`t1_member`.`firstname`,
`t1_member`.`lastname`, /* desired */
`t1_news`.`id` AS `t1_news_id`,
`t1_news`.`headline` /* desired */
FROM
`int_news`
LEFT JOIN `tl_member` ON `int_news`.`member_id` = `tl_member`.`id`
LEFT JOIN `tl_news` ON `int_news`.`news_id` = `tl_news`.`id`
";
$res = mysql_query($query);
$arrHeadings = array();
while($row = mysql_fetch_assoc($res)) {
// We want to output the results in groups of headings
$arrHeadings[$row['heading']][] = $row;
}
// Don't forget to cleanse for html output (unlike below)
// Loop through the headers
foreach($arrHeadings as $heading=>$arrRow) {
echo '<dl>';
echo '<dt>'.$heading.'</dt>';
echo '<dd>';
// Loop through rows with the same header
foreach($arrRow as $index=>$dbRow) {
echo $dbRow['lastname'].'<br />';
}
echo '</dd>';
echo '</dl>';
}
?>

Categories