homepage Welcome to WebmasterWorld Guest from 54.211.164.132
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member
Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
Forum Library, Charter, Moderators: coopster & jatar k

PHP Server Side Scripting Forum

    
Creating Multidimentional Array From SQL Statement
doubleJ




msg:4469812
 7:55 pm on Jun 26, 2012 (gmt 0)

Hello...
I have 3 sql tables for event information.
1 table is for the venue (address, phone, etc...).
1 table for the actual event information (speaker, date, etc...).
1 table is an intermediate "join" table (1 venue could be used for multiple events and events could span multiple days or have multiple sessions per day).

Table example...

TblSermon:
ID Date Time Speaker
----------------------------------
122 2012-09-18 "09:00 AM" "Joshua Jackson"
123 2012-09-18 "11:00 AM" "Joshua Jackson"
1452 2014-02-25 "06:00 PM" "JoJo The Idiot Circus Boy"

TblLocation:
ID Location City State
-------------------------------------------
14 "Omega Arena" Boston MA
1263 "Kentucky Civic Center" Lexingon KY

TblJoinSermonLocation:
ID MeetingName Location Sermon
-----------------------------------
323 "Special Times" 14 122
324 "Special Times" 14 123
345 "Journeys" 1263 1452


Query example...

SELECT TOP (100) PERCENT dbo.TblSermon.Date, dbo.TblSermon.Time, dbo.TblSermon.Speaker, dbo.TblJoinSermonLocation.MeetingName, dbo.TblLocation.Location, dbo.TblLocation.City, dbo.TblLocation.State
FROM dbo.TblLocation RIGHT OUTER JOIN dbo.TblJoinSermonLocation ON dbo.TblLocation.ID = dbo.TblJoinSermonLocation.Location RIGHT OUTER JOIN dbo.TblSermon ON dbo.TblJoinSermonLocation.Sermon = dbo.TblSermon.ID
WHERE (dbo.TblSermon.Date >= { fn NOW() })
ORDER BY dbo.TblSermon.Date, dbo.TblSermon.Time


Obviously, this will list all information (Date, Time, Speaker, MeetingName, Location, City, State) for each record that matches.
What I'm looking for is the ability to show each venue (Location) once and then list all the dates/times associated with that event, under it.
There's no point in duplicating MeetingName, Location, City, State for each record.

Array example...

Array
(
[Location] => Omega Arena
[City] => Boston
[State] => MA
[MeetingName] => Special Times
[Date] => 2012-09-19 00:00:00.000
[Time] => 09:00 AM
[Speaker] => Joshua Jackson
)
Array
(
[Location] => Omega Arena
[City] => Boston
[State] => MA
[MeetingName] => Special Times
[Date] => 2012-09-19 00:00:00.000
[Time] => 11:00 AM
[Speaker] => Joshua Jackson
)


My theory is that I can create a multidimensional array where the first level is the venue info (Location, City, State), the second level is the event info (MeetingName), and the third are the dates/times).

Array example...

Array
(
[Location] => Omega Arena
[City] => Boston
[State] => MA
Array
(
[MeetingName] => Special Times
Array
(
[Date] => 2012-09-19 00:00:00.000
[Time] => 09:00 AM
[Speaker] => Joshua Jackson
)
Array
(
[Date] => 2012-09-19 00:00:00.000
[Time] => 11:00 AM
[Speaker] => Joshua Jackson
)
)
)


Unfortunately, I haven't figured out how to do that.
Hehehe...
Can you guys help me out?
BTW...
How do you indent, here?
JJ

 

rocknbil




msg:4470172
 4:35 pm on Jun 27, 2012 (gmt 0)

I wouldn't do an array. Arrays need to be stored in memory, and the more memory you use, the slower things get. Additionally, once you construct your arrays, you'll have to do all your sorting and output in programming, and you can leverage the power of mySQL to make your job a lot easier.

I would do some sort of toggle so it will only output a "new name" if the name value has changed. For example, simplifying so you can see the concept,


$rows=$currName=null;
while (list($name,$event,$date) = mysql_fetch_array($result)) {
if ($name==$currName) { $displayName=' '; }
else { $displayName=$currName=$name; }
$rows .= "
<tr>
<td>$displayName</td>
<td>$event</td>
<td>$date</td>
</tr>
";
}
if ($rows) { echo "<table>$rows</table>"; }
else { echo "<p>No results were found.</p>"; }


Some notes:

- as always, not working code typed on the fly for example only.

- This
$rows=$currName=null;
1) is just good programming (always initialize any variables you use) and 2) prevents "undefined variable" warnings the first time you go through the loop and concatenate the variable $rows. They may not display in the browser, but will clog up your error logs fast, even though they're just warnings.

- Yes, the previous stores a scalar string in memory, it's just a lot less data to store. :-) This approach allows you to easily do the very important if/else (what if nothing is found?) Additionally as mentioned you don't have to jump through hoops in programming working with the arrays.

- as you can see this "tracks" the "name" in the current row with the variable $currName. If it's the same as the last row, it displays a non breaking space (because tables display weird in IE if empty,) otherwise it displays the name and should only do so once for each of the same value (be sure to add order by event_date desc, event_name asc in your select). Rinse and repeat for other recurrent values (phone, etc.)

- This
list($name,$event,$date)

is a little used shortcut to

while ($row = mysql_fetch_array($result)) {
$name = $row['name']; // or $row[0]
$event = $row['event']; // or $row[1]
$date = $row['event_date']; // or $row[2]


... and works very well because mysql_fetch_array() returns both an associative and an indexed array, and we're using the latter to leverage with list().

- The above is formatted using the pre tags (find them in the links below posting) and doesn't allow tabs. Use only spaces. Many people use the quote tags to do a similar thing.

doubleJ




msg:4470191
 5:55 pm on Jun 27, 2012 (gmt 0)

Thanks for the insightful response.
I had played around with list() but never got the results I was looking for (presumably because I didn't do the $currName part).
I am using PDO and MSSQL, so my db code will be a little different.
I think I can hack it together, though.

Thanks for the "pre" idea.

JJ

doubleJ




msg:4470210
 7:10 pm on Jun 27, 2012 (gmt 0)

Ok...
I wasn't figuring out your
list(), after all.
Here is what I ended up with and I think it produces the same results.

<?php
try {
$dbh = new PDO("sqlsrv:Server=localhost;Database=Sermons", "", "");
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT TOP (100) PERCENT dbo.TblSermon.Day, dbo.TblSermon.Date, dbo.TblSermon.Time, dbo.TblSermon.Speaker, dbo.TblSermon.Series, dbo.TblSermon.Sarasota, dbo.TblSermon.NonFlc, dbo.TblJoinSermonLocation.MeetingName, dbo.TblLocation.Location, dbo.TblLocation.Pastors, dbo.TblLocation.Address, dbo.TblLocation.City, dbo.TblLocation.State, dbo.TblLocation.Zip, dbo.TblLocation.Country, dbo.TblLocation.Phone, dbo.TblLocation.Email, dbo.TblLocation.WebAddress
FROM dbo.TblLocation RIGHT OUTER JOIN dbo.TblJoinSermonLocation ON dbo.TblLocation.ID = dbo.TblJoinSermonLocation.Location RIGHT OUTER JOIN dbo.TblSermon ON dbo.TblJoinSermonLocation.Sermon = dbo.TblSermon.ID
WHERE (dbo.TblSermon.Date >= { fn NOW() })
ORDER BY dbo.TblSermon.Date, dbo.TblSermon.Time";
$stmt = $dbh->prepare($sql);
$stmt->execute();
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$count = 0;
$rows = $currName = null;
foreach ($stmt as $row) {
if ($row["Location"] == $currName) {
$displayName = "&nbsp;";
} else {
$displayName = $currName = $row["Location"];
}
$rows .= " <tr> <td>" . $displayName . "</td> <td>" . $row["MeetingName"] . "</td> <td>" . $row["Date"] . "</td> </tr> ";
$count++;
}
if ($rows) {
echo "<table>" . $rows. "</table>";
} else {
echo "<p>No results were found.</p>";
}
unset($row);
if ($count == 0) {
echo "No scheduled events";
}
$dbh = null;
}
catch(PDOException $e) {
echo $e->getMessage();
}
?>

What is the difference in how these two work?
Is one intrinsically better than the other?
JJ

doubleJ




msg:4470219
 7:42 pm on Jun 27, 2012 (gmt 0)

What is the purpose of . in
$rows .= " <tr> <td>" . $displayName . "</td> <td>" . $row["MeetingName"] . "</td> <td>" . $row["Date"] . "</td> </tr> ";?
When I took it out, only 1 result was displayed (instead of 10-15).
JJ

doubleJ




msg:4470240
 8:33 pm on Jun 27, 2012 (gmt 0)

Ok...
I found a big wrench in the plan.
The reason that I was looking at a multidimensional array was that I would be able to nest the bits of information, appropriately.
For instance...

Upcoming Events
Special Times
Omega Arena (Boston, MA)
Session One
Date: September 19th @ 09:00AM
Speaker: Joshua Jackson
Session Two
Date: September 19th @ 11:00AM
Speaker: Joshua Jackson

I don't seem to be able to do that with the afore-mentioned code, since each record produces a line with all the fields (albeit black for some).
This is great for tabular data, though.
JJ

rocknbil




msg:4470505
 4:09 pm on Jun 28, 2012 (gmt 0)

Ehh . . you just discoverd the problem with pre, you need to break long lines. :-) A mod will be along to fix it soon . . .

What is the purpose of . in $rows .= " .....

This approach (concatenating to $rows) allows you to easily do the very important if/else (what if nothing is found?)


Concatenating is "adding to a string as needed"

$me = 'Meoh ';
$me .= ' Myoh';
echo $me; // "Meoh Myoh"

The reason that I was looking at a multidimensional array was that I would be able to nest the bits of information, appropriately.


You should still be able to do that. You just "nest" your display items. In the same way you're "tracking" the outer event name, you have a variable inside to display stuff as the sessions change (or not.)

doubleJ




msg:4470525
 4:36 pm on Jun 28, 2012 (gmt 0)


Concatenating is "adding to a string as needed"
$me = 'Meoh ';
$me .= ' Myoh';
echo $me; // "Meoh Myoh"

I guess this is the same, but what I normally do is...

$me = 'Meoh ';
$me = $me . ' Myoh';
echo $me; // "Meoh Myoh"

Is there a time when
.= is better than = $variable?


You should still be able to do that. You just "nest" your display items. In the same way you're "tracking" the outer event name, you have a variable inside to display stuff as the sessions change (or not.)

Hmmm...
I'm trying to wrap my head around the idea of that.
The only way that I can think how that would even work would be to define a butt-load (that's a metric butt-load, btw...) of variables ($session1date, $session1time, $session1speaker, $session2date, $session12date, etc...).
One particular event that we have, each year, has 7 sessions over 3 days with 2 speakers.
Maybe I'm looking at it backwards.
I know there is the ability to do
for ($i,$i<something,$i++) {}, but I haven't used that very much.
I guess I just think more like arrays (like nested ordered lists in html).
Hehehe...
Speaking of nested lists, that it how I would probably code this data.
The way I'm taking your concept is almost like I would need to nest
foreach over and over to get the information that I want.
I'm assuming that's not what you mean, since that seems like it would be a lot of overhead and processing time.
That's just the only way I can get your concept.
JJ

rocknbil




msg:4470986
 4:27 pm on Jun 29, 2012 (gmt 0)


Is there a time when .= is better than = $variable?


When you're inside a loop where inline concatenation isn't possible - as above. :-)

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved