MultiSelect Load Efficiency using PHP - php

I'm looking for a more efficient way of loading a mutliselect list this theory could apply to many situations. The way I do it causes many queries and I was wondering if there is a way to do it in two db queries.
DB Table : users: fields= (userID, name)
data: 1, Dan
data: 2, Cory
data: 3, Matt
DB Table : users_selected: fields(userSelectedID, userID)
data: 1,1
Now with php I normally do the following:
<?php
$q = 'SELECT userID,name FROM users';
$r = mysql_query($r);
echo '<select id="assignToID" name="assignToID[]" multiple="assignToID">';
while($e = mysql_fetch_array($r){
//this is where you have to query the db each time... theres got to be a better way
$q2 = 'SELECT userSelectedID FROM user_selected WHERE userID = "'.$e['userID'].'" ';
$r2 = mysql_query($q2);
$nr = mysql_num_rows($r2);
if($nr>0){
$sel = ' selected="selected" ';
}
else{
$sel = '';
}
echo '<option '.$sel.' value="'.$e['userID'].'"'>'.$e['name'].'</option>';
}
echo '</select>'
?>
So above we have to query for every user we have in the DB in our loop. Is there a way using PHP array_merge or someway to just do one query for all the users then append weather they are selected or not... Just trying to find a more elegant and efficient solution.
Many Thanks

Yes, there is such a way, to get what you need in 1 SQL Query.
SELECT * FROM users
LEFT OUTER JOIN user_selected
ON users.userID = user_selected.userID
This LEFT OUTER JOIN, should and will produce a complete set of recors from table users, witht he matching records (if available) from user_selected. If there is no match, the right side will just contain null.

Related

More efficient way to grab MySQL row populated with single value

Right now I'm trying to set a variable from an SQL response without doing it more than necessary.
The situation is I have a SQL result from a SELECT + JOIN query with a user_id column that has only a single value. The other columns are different per row and I need to loop through them for that data. I was wondering if there was a way to extract the homogeneous value from the user_id column without setting it over and over again to a variable in my while loop.
Code:
#where I would like the $user_id to be set
while($responseArray = $response->fetch_assoc()){
$userId = $responseArray["user_id"]; #what I don't want to do
#other fetching stuff
}
SQL:
SELECT users.username, users.user_id, posts.post_id, posts.post_content, posts.number_comments, comments.comment_id, comments.comment_post_id
FROM users
JOIN posts
JOIN comments
WHERE delete_bit = 0 AND username = "john";
You cannot get away from fetching at least one result row. Even the fetchOne()-type functions do this. But if you only want a single row, why even bother using a loop in the first place?
$result = $db->query(...);
$row = $result->fetchRow();
$value = $row['somefield'];
would be far better than something silly like
$result = $db->query(...);
while($row = $result->fetchRow()) {
$value = $row['somefield'];
break;
}

PHP - Getting num_rows of different ID's without writing new statements?

Basically, I'm coding a site that has many different categories and I want to display the amount of rows specific to that ID.
So for example, I have as the query:
$query= "SELECT job_sec FROM jobs WHERE job_sec = ?";
mysqli_num_rows($query);
I need to know how I can count the rows of an ID then echo the rows counted.
I'd like the results to display:
Web Design: 2,001 jobs
Logo Design: 5,120 Jobs
The job_sec column just uses a numerical value, would it be easier to have a text value then count the rows relating to the text value and echo them?
I have a feeling I need to use an array however I need the most efficient method.
Any help would be much appreciated!
Assuming job_sec is the category and I think you are looking for "group by":
$sql= "SELECT job_sec, count(*) AS c FROM jobs GROUP BY job_sec";
$r = mysqli_query($sql);
while ($row = mysqli_fetch_assoc($r)) {
echo $row['job_sec'] . ': ' . $row['c'] . ' Jobs ';
}
(didn't test and not sure if the mysqli syntax is correct)

Left join MySql/PHP

Whilst populating a table based on ids and labels from different tables, it appeared apparent there must potentially be a better way of achieving the same result with less code and a more direct approach using LEFT JOIN but i am puzzled after trying to work out if its actually capable of achieving the desired result.
Am i correct in thinking a LEFT JOIN is usable in this instance?
Referencing two tables against one another where one lists id's related to another table and that other table has the titles allocated for each reference?
I know full well that if theres independent information for each row LEFT JOIN is suitable, but where theres in this case only several ids to reference for many rows, i just am not clicking with how i could get it to work...
The current way i am achieving my desired result in PHP/MySQL
$itemid = $row['item_id'];
$secid = mysql_query(" SELECT * FROM item_groups WHERE item_id='$itemid' ");
while ($secidrow = mysql_fetch_assoc($secid)) {
//echo $secidrow["section_id"]; //testing
$id = $secidrow["section_id"];
$secnameget = mysql_query(" SELECT * FROM items_section_list WHERE item_sec_id='$id' ");
while ($secname = mysql_fetch_assoc($secnameget)) {
echo $secname["section_name"];
}
}
Example of the data
Item groups
:drink
:food
:shelf
Item List
itemId, groupId
Group List
groupId, groupTitle
The idea so outputting data to a table instead of outputting "Item & Id Number, in place of the ID Number the title actually appears.
I have achieved the desired result but i am always interested in seeking better ways to achieve the desired result.
If I've deciphered your code properly, you should be able to use the following query to get both values at the same time.
$itemid = $row['item_id'];
$secid = mysql_query("
SELECT *
FROM item_groups
LEFT JOIN items_section_list
ON items_section_list.item_sec_id = item_groups.section_id
WHERE item_id='$itemid'
");
while ($secidrow = mysql_fetch_assoc($secid)) {
//$id = $secidrow["section_id"];
echo $secidrow["section_name"];
}

SQL Query Optimization help

my foundation on SQL is pretty weak so I hope you could bear with me. I have three tables: contents, categories, and categorization. The setup was chosen since some content will belong to one or more categories.
I want to fetch contents and its corresponding categories.
This is an overly-simplified version of the current script, without error-checking routines:
$q = "SELECT * FROM contents WHERE contents.foo = 'bar'"
$resource = mysql_query($q);
$categoryFilter = array();
$q2 = "SELECT * FROM categorization WHERE ";
while($content = mysql_fetch_assoc($resource))
{
$categoryFilter[] = "content_id='" . $content["id"] . "'";
}
if(count($categoryFilter))
{
$q2 .= implode(" OR ", $categoryFilter);
mysql_query($q2);
}
That's the gist of it. I hope you get what I am trying to do. I don't know if I can actually use JOINS the content_id may be present in multiple rows in categorization. So what I did was to simply append multiple OR's, trying to fetch items one by one. I really would not like to use multiple queries in this scenario. I hope anyone could suggest an approach
Thanks for your time
One query should be enough to fetch data from all three tables:
SELECT categories.category_id #, other fields
FROM contents
INNER JOIN categorization ON contents.content_id = categorization.content_id
INNER JOIN categories ON categorization.category_id = categories.category_id
WHERE contents.content_id = 1 # AND other filters
Tweak the columns in the SELECT clause and/or conditions in WHERE clause according to your needs.
This should do the same thing as in your example:
$q = "
SELECT *
FROM
contents c
categorization ctg ON ctg.content_id = c.id
WHERE c.foo = 'bar'
";
$result = mysql_query($q);
If I understand it correctly, you can do this in one sql statement
SELECT *
FROM contents t1
JOIN categorization t2
WHERE t1.content_id = t2.content_id AND t1.foo = 'bar'
Also ensure that content_id is indexed both in 'content' and 'categorization'. You may find it worthwhile indexing 'foo' aswell, but it depends on how you are actually searching.

Subquery in PHP

Let's put an easy example with two tables:
USERS (Id, Name, City)
PLAYERS (Id_Player, Number, Team)
And I have to do a query with a subselect in a loop, where the subselect is always the same, so I would like to divide it into two queries and put the subselect outside the loop.
I explain. What works but it is not optimize:
for($i=0;$i<something;$i++)
{
$res2=mysql_query("SELECT Team from PLAYERS WHERE Number=$i
AND Id_Player IN (SELECT Id FROM USERS WHERE City='London')");
}
What I would like to do but it doesn't work:
$res1=mysql_query("SELECT Id from USERS where City='London'");
for($i=0;$i<something;$i++)
{
$res2=mysql_query("SELECT Team from PLAYERS WHERE Number=$i
AND Id_Player IN **$res1**");
}
Thanks!
Something like this should work.
<?
$sql = "SELECT Team from PLAYERS
JOIN USERS on (Id_player=Id)
WHERE Number BETWEEN $minID AND $maxID
AND City='London'
GROUP BY Team";
$results=mysql_query($sql) or die(mysql_error());
// $results contain all the teams from London
// Use like normal..
echo "<ul>\n";
while($team = mysql_fetch_array($results)){
echo "\t<li>{$team['Team']}</li>\n";
}
echo "</ul>";
Placing SQL quires in loops can be very slow and take up a lot of resources, have a look at using JOIN in you SQL. It's not that difficult and once you've got the hang of it you can write some really fast powerful SQL.
Here is a good tutorial worth having a look at about the different types of JOINs:
http://www.keithjbrown.co.uk/vworks/mysql/mysql_p5.php
SELECT PLAYERS.*, USERS.City FROM PLAYERS, USERS WHERE USERS.City='London' AND PLAYERS.Number = $i
Not the best way to do it; maybe a LEFT JOIN, but it should work. Might have the syntax wrong though.
James
EDIT
WARNING: This is not the most ideal solution. Please give me a more specific query and I can sort out a join query for you.
Taking your comment into account, let's take a look at another example. This will use PHP to make a list we can use with the MySQL IN keyword.
First, make your query:
$res1 = mysql_query("SELECT Id from USERS where City='London'");
Then, loop through your query and put each Id field one after another in a comma seperated list:
$player_ids = "";
while($row = mysql_fetch_array($res1))
{
$player_ids .= $row['Id'] . ",";
}
$player_ids = rtrim($player_ids, ",");
You should now have a list of IDs like this:
12, 14, 6, 4, 3, 15, ...
Now to put it into your second query:
for($i = 0; $i<something; $i++)
{
$res2 = mysql_query("SELECT Team from PLAYERS WHERE Number=$i
AND Id_Player IN $player_ids");
}
The example given here can be improved for it's specific purpose, however I'm trying to keep it as open as possible.
If you want to make a list of strings, not IDs or other numbers, modify the first while loop, replacing the line inside it with
$player_ids .= "'" . $row['Id'] . "',";
If you could give me your actual query you use, I can come up with something better; as I said above, this is a more generic way of doing things, not necessarily the best.
Running query in a loop is not a great idea. Much better would be to get whole table, and then iterate through table in loop.
So query would be something like that:
"SELECT Team from PLAYERS WHERE Number BETWEEN($id, $something)
AND Id_Player IN (SELECT Id FROM USERS WHERE City='London')"
$res1=mysql_query("SELECT Id from USERS where City='London'");
for($i=0;$i<something;$i++)
{
$res2=mysql_query("SELECT Team from PLAYERS WHERE Number=$i
AND Id_Player IN **$res1**");
}
Would work, but mysql_query() returns a RESULT HANDLE. It does not return the id value. Any select query, no matter how many, or few, rows it returns, returns a result statement, not a value. You first have to fetch the row using one of the mysql_fetch...() calls, which returns that row, from which you can then extract the id value. so...
$stmt = mysql_query("select ID ...");
if ($stmt === FALSE) {
die(msyql_error());
}
if ($stmt->num_rows > 0) {
$ids = array();
while($row = mysql_fetch_assoc($stmt)) {
$ids[] = $row['id']
}
$ids = implode(',', $ids)
$stmt = mysql_query("select TEAM from ... where Id_player IN ($ids)");
.... more fetching/processing here ...
}

Categories