I am seeking some advice on the best way to retrieve and display my data using MySQL and PHP.
I have 3 tables, all 1 to many relationships as follows:
Each SCHEDULE has many OVERRIDES and each override has many LOCATIONS. I would like to retrieve this data so that it can all be displayed on a single PHP page e.g. list out my SCHEDULES. Within each schedule list the OVERRIDES, and within each override list the LOCATIONS.
Option1 - Is the best way to do this make 3 separate SQL queries and then write these to a PHP object? I could then iterate through each array and check for a match on the parent array.
Option 2 - I have thought quite a bit about joins however doing two right joins will return me a row for every entrance in all 3 tables.
Any thoughts and comments would be appreciated.
Best regards, Ben.
If you really want every piece of data, you're going to be retrieving the same number of rows, no matter how you do it. Best to get it all in one query.
SELECT schedule.id, overrides.id, locations.id, locations.name
FROM schedule
JOIN overrides ON overrides.schedule_id = schedule.id
JOIN locations ON locations.override_id = overrides.id
ORDER BY schedule.id, overrides.id, locations.id
By ordering the results like this, you can iterate through the result set and move on to the next schedule whenever the scheduleid changes, and the next location when the locationid changes.
Edit: a possible example of how to turn this data into a 3-dimensional array -
$last_schedule = 0;
$last_override = 0;
$schedules = array();
while ($row = mysql_fetch_array($query_result))
{
$schedule_id = $row[0];
$override_id = $row[1];
$location_id = $row[2];
$location_name = $row[3];
if ($schedule_id != $last_schedule)
{
$schedules[$schedule_id] = array();
}
if ($override_id != $last_override)
{
$schedules[$schedule_id][$override_id] = array();
}
$schedules[$schedule_id][$override_id][$location_id] = $location_name;
$last_schedule = $schedule_id;
$last_override = $override_id;
}
Quite primitive, I imagine your code will look different, but hopefully it makes some sense.
Related
I have a MySQLi query that returns all of the "assets" assigned to an employee based on their EmployeeID. This works great. The problem I'm facing is in the presentation.
I have an HTML table that has two sections: 1 for Hardware and 1 for software. What I am hoping to avoid is having to perform separate lookups that generate separate result sets for each type of asset. The end result needs to display as follows:
I can build the table just fine. The result sets contains a field of asset_type but I've not had any luck figuring out the code to use to iterate through my single result set. Is this even possible? Can I pull just the hardware assets from the result set with a while? Perhaps a
while($result['asset_type'] == "hardware"){
echo ""; // table row code
}
And then repeat the same thing later in my table code for asset_type software?
UPDATE 1
The code I've thought might work so far, but isn't doing anything, is
// SQL query
$q = "SELECT * FROM `assets_table` WHERE `emp_id` = '".$emp_id."'";
$r = mysqli_query($connect, $q);
$total_assets = mysqli_num_rows($r);
while($r){
if($r['category'] = "hardware"){
echo $r['asset_name']." - ".$r['hw_make']." ".$r['hw_model'];
}
}
I ended up going ahead and breaking out the query into multiple result sets and dealing with them that way. It'd be awesome if you could have a while() with a WHERE statement when iterating through result sets / arrays.
i dont know if i am doing right or wrong, please dont judge me...
what i am trying to do is that if a record belongs to parent then it will have parent id assosiated with it.. let me show you my table schema below.
i have two columns
ItemCategoryID &
ItemParentCategoryID
Let Suppose a record on ItemCategoryID =4 belongs to ItemCategoryID =2 then the column ItemParentCategoryID on ID 4 will have the ID of ItemCategoryID.
I mean a loop with in its own table..
but problem is how to run the select query :P
I mean show all the parents and childs respective to their parents..
This is often a lazy design choise. Ideally you want a table for these relations or/and a set number of depths. If a parent_id's parent can have it's own parent_id, this means a potential infinite depth.
MySQL isn't a big fan of infinite nesting depths. But php don't mind. Either run multiple queryies in a loop such as Nil'z's1, or consider fetching all rows and sorting them out in arrays in php. Last solution is nice if you pretty much always get all rows, thus making MySQL filtering obsolete.
Lastly, consider if you could have a more ideal approach to this in your database structure. Don't be afraid to use more than one table for this.
This can be a strong performance thief in the future. An uncontrollable amount of mysql queries each time the page loads can easily get out of hands.
Try this:
function all_categories(){
$data = array();
$first = $this->db->select('itemParentCategoryId')->group_by('itemParentCategoryId')->get('table')->result_array();
if( isset( $first ) && is_array( $first ) && count( $first ) > 0 ){
foreach( $first as $key => $each ){
$second = $this->db->select('itemCategoryId, categoryName')->where_in('itemParentCategoryId', $each['itemParentCategoryId'])->get('table')->result_array();
$data[$key]['itemParentCategoryId'] = $each['itemParentCategoryId'];
$data[$key]['subs'] = $second;
}
}
print_r( $data );
}
I don't think you want/can to do this in your query since you can nest a long way.
You should make a getChilds function that calls itself when you retrieve a category. This way you can nest more than 2 levels.
function getCategory()
{
// Retrieve the category
// Get childs
$childs = $this->getCategoryByParent($categoryId);
}
function getCategorysByParent($parentId)
{
// Get category
// Get childs again.
}
MySQL does not support recursive queries. It is possible to emulate recursive queries through recursive calls to a stored procedure, but this is hackish and sub-optimal.
There are other ways to organise your data, these structures allow very efficient querying.
This question comes up so often I can't even be bothered to complain about your inability to use Google or SO search, or to offer a wordy explanation.
Here - use this library I made: http://codebyjeff.com/blog/2012/10/nested-data-with-mahana-hierarchy-library so you don't bring down your database
I am wondering if there is a way to do what I am doing more efficiently. Right now, I have a class that retrives statuses from the database. It's pretty simple and shouldn't really effect performance all that much.
public function get ($var1, $var2, $var3)
{
$feed = array(); //Initialize an empty array
//Query the database
$Statement = $this->Database->prepare("SELECT id, name, excerpt, post, timestamp, tags, title FROM posts WHERE col1 = ? AND col2 = ? AND col3 = ? ORDER BY id DESC LIMIT 15");
$Statement->execute(array($var1, $var2, $var3));
while($row = $Statement->fetch(PDO::FETCH_ASSOC))
{
$posts[] = array( "id" => $row["id"], /*etc...*/ );
}
return $posts;
} //end get
And then my page set up something like this which I know is not efficient at all:
<?php for ($count = 1; $count <= $total; $count++): //Display the calendar
echo $count;
$feed = $Feed->get($count, $total, $var3);
foreach ($feed as $post):
echo $post["id"];
endforeach;
endfor; ?>
I hope that makes sense. There's a lot more html thrown in there and everything. Right now there are only 18 rows in my database, and it takes 10 seconds to load the page. Which is really bad. I have to set it up this way because of the design of the site. So the foreach loop has to be within the for loop because the whole thing is set up as a calendar.
My question is whether it would be more efficient to select all of the rows, save them outside of the for loop and then work with that array, or whether it's better to run each query inside the foreach loop the way I'm doing it now (i've read a lot, and know that most people say this is a huge no no). And what kind of issues would I run into if I used the former option and there were say a million rows in the database.
I hope that makes sense. I'll update the question if it doesn't. Right now though about 30 queries are being made to only access 1 or 2 rows. But the only other option I could come up with is selecting all of the rows in the table, and then working with that array, but if there are pretend 1 million rows in the db, I feel like that would affect performance a lot more.
Am I right, and what are some solutions? Thanks
I just want to point out that I did resolve the issue. If anyone is wondering why the foreach loop was querying so sow it was because I accidentally deleted a line where I connected to the Facebook api within the foreach loop every time to gather the poster's information. So if anyone ever stumbles upon this question, just to be sure I want to clarify that making many facebook->api calls is a bad thing. save the info in your database and query that instead.
I have a mysql query that retrieves all my topic results. I then have a pagination system where results are separated into pages and the query's limit #,# changes based on what page you are on.
What I want to do is put all those results into two separate div containers. I want 21 results on each page. The first 9 I will put in one div. The next 12 will go in the other. Does anyone know an efficient way to do this? Should I use two queries, or javascript, or another way? I am just looking for the best most efficient way to do this. Unfortunately the pagination system makes two queries difficult. Any suggestions highly appreciated.
$sql = "SELECT * FROM topics LIMIT ?,?";
$stmt2 = $conn->prepare($sql);
$result=$stmt2->execute(array(somenumber,somenumber2));
I don't see any reason why you can't do a single MySQL query and use JavaScript to sort the results. Understand that I don't understand here what your data is coming back looking like, so any example I provide will have to remain pretty agnostic in this regard.
I will, however, assert as an assumption that you have a JavaScript array of length 21 with some data that is the basis for your display.
Assuming that we're just talking about the first 9, and the last 12, the sorting code is as simple as:
// assume my_array is the array mentioned above
for (var i = 0; i < 9; i += 1) {
var html = code_to_transform_data_from_array(array[i]);
$('.div1').append($(html));
}
for (var i = 9; i < 21; i += 1) {
var html = code_to_transform_data_from_array_b(array[i]);
$('.div2').append($(html));
}
If your sorting condition is any more complicated, then you'd be better off with something like...
while (my_array.length > 0) {
var item = my_array.pop();
if (sorting_condition) {
$('.div1').append(f1(item));
}
else {
$('.div2').append(f2(item));
}
}
(In the second example, I became a lazy typist and assumed f1 and f2 to be complete transformation functions. sorting_condition is your criteria for determining in which bucket something goes.
Hope that sets you off on the right track.
I'm using an if clause to fetch the value of my mysql table data because my table schema is not normal.
now for getting these values, I wrote the below code:
$result = $db->sql_query("SELECT type, var, count from table_counter");
while ($row = $db->sql_fetchrow($result)) {
$type = $row['type'];
$var = $row['var'];
$count = intval($row['count']);
if(($type == "total") && ($var == "visits")) {
$totalVisits= $count;
}elseif(($type == "total") && ($var == "pageviews")) {
$totalPVisits= $count;
}
}
Is there any other way rather than using an if clause?!
SELECT `type`, `var`, SUM(`count`) AS `sum`
FROM table_counter
GROUP BY `type`,`var`;
There's no need for that intval() to convert the count field to integer. It's already defined as an integer in your MySQL table.
What you have here is some kind of EAV data structure and the if is a common way to fetch from it. There are other ways of pivoting them.
What are you aiming to do with the data? Just create the counts?
You could extract the data in more than one query.
Another option is to put the data into an array, then sort it using PHP array sort functions. It could then be split it into two separate arrays, if needed.
You will need to pivot the data. And that will require you to write some code to parse out what you need in php and mysql. This will can get heavy depending on how much data you want and how it's stored and how it needs to be retrieved. Based on your question text it looks you are storing very simple data, but for every type and set of data you are storing you will need to create logic for it.
Soooo, if you know exactly what the variables are going to be you could set up and array of the variable names you want set and loop through them.
$legal_values = array('visits', 'pageviews', etc...);
while ($row = $db->sql_fetchrow($result)) {
if (in_array($row['var'], $legal_values)) {
$$row['var'] = $intval($row['count'];
}
}
This is just a simple example and only works if all the types are count. Obviously if you want to filter it down you will need more logic. There isn't really a catch-all solution for this stuff, so it comes down to writing something that is simple so you understand it and you can easily extend it to handle more data that you might need later.
${$row['type'] . ucfirst($row['var'])} = $row['count'];
That reads total pageviews 107 to $totalPageviews = 107. Depending on where you want to use this, this may be a possibility.