Fetch data based on another MySQL query - php

I have the following two queries. The first query is fetching a key called srNumber from first table called tags and then the second query is using that srNumber to fetch details from a second table called nexttable.
$tagQuery = "SELECT * FROM tags WHERE status = 0 AND currentStage = '1' AND assignedTo = '1' ORDER BY
deliveryDate ASC";
$tagQueryExecute = mysqli_query($conn, $tagQuery);
while($rows = mysqli_fetch_array($tagQueryExecute)){
$srNumber = $rows['srNumber'];
$nextQuery = "SELECT * FROM nexttable WHERE srNumber='$srNumber'";
$nextQueryExecute = mysqli_query($conn, $nextQuery);
$detailsFromNextTable = mysqli_fetch_array($nextQueryExecute);
//Show these details
}
For a small result this is not a big issue. But if the first query got so many results, then second query has to run as many times as number of loop. Is there any other way to do this efficiently?
NB: Please ignore the SQL injection issues with these queries. I just simplified it to show the problem

As you appear to have only 1 row in the second table, you would be better off with a join, MySQL: Quick breakdown of the types of joins gives some more info on the types of joins.
SELECT *
FROM tags t
JOIN nexttable n on t.srNumber = n.srNumber
WHERE t.status = 0 AND t.currentStage = '1' AND t.assignedTo = '1'
ORDER BY t.deliveryDate ASC
This also removes the SQL injection as well.
I would also recommend removing the * and just list the columns you intend to use, this also helps if you have columns with the same names in the different tables as you can add an alias to the specific columns.
FYI - the original problem you have is similar to What is the "N+1 selects problem" in ORM (Object-Relational Mapping)?

Related

How to insert a particular value from one database table into another using '$row'?

I am currently trying to make a system which selects a user at random from the table 'users' and appends it to another table 'agreeuser' or 'disagreeuser' depending on whether or not the user has the 'opinion' value of 'like' or 'dislike'. I am doing this by using $row to select the full row where the user has the opinion of 'like', but it doesn't seem to be adding the data stored in '$row[username]' to the 'user' column of the 'agreeuser' or 'disagreeuser' table.
I have already tried storing the '$row['username'] value as a variable and using this in the value aspect of the query, but it doesn't seem to have worked. I have also tried combining the INSERT and SELECT queries and it still has no effect. Can anyone tell me what I am doing wrong, please? :)
if($_SESSION['pageLoaded'] != "true") {
$selectLikesQuery = "SELECT * FROM users WHERE opinion = 'like' ORDER BY RAND() LIMIT 1";
$likeSelectorResult = mysqli_query($userConnect, $selectLikesQuery);
while($row = mysqli_fetch_assoc($likeSelectorResult)) {
$removeCurrentAgreeContent = "TRUNCATE TABLE agreeUser";
$addAgreeUserQuery = "INSERT INTO agreeUser (user) VALUE ('$row[username]')";
mysqli_query($chatConnect, $removeCurrentAgreeContent);
mysqli_query($chatConnect, $addAgreeUserQuery);
}
$selectDislikesQuery = "SELECT * FROM users WHERE opinion = 'dislike' ORDER BY RAND() LIMIT 1";
$dislikeSelectorResult = mysqli_query($userConnect, $selectDislikesQuery);
while($row = mysqli_fetch_assoc($dislikeSelectorResult)) {
$removeCurrentDisagreeContent = "TRUNCATE TABLE disagreeUser";
$addDisagreeUserQuery = "INSERT INTO disagreeUser (user) VALUE ('$row[username]')";
mysqli_query($chatConnect, $removeCurrentDisagreeContent);
mysqli_query($chatConnect, $addDisagreeUserQuery);
}
$_SESSION['pageLoaded'] = "true";
}
I need the username from 'users' to be inserted into the 'user' column of 'agreeuser'. Thanks for any help, and apologies if I'm doing something stupid :)
Why don't you use SQL views to just see needed data in "a virtual table", instead of creating duplicate data?
Views is a very helpful feature.
For example, make a SELECT query to find needed rows:
SELECT * FROM users WHERE opinion = 'dislike'
If this select suits you, just add:
CREATE OR REPLACE VIEW v_agreeUsers AS SELECT * FROM users WHERE opinion = 'dislike'
And make the same for users who agree:
CREATE OR REPLACE VIEW v_disagreeUsers AS SELECT * FROM users WHERE opinion = 'like'
To be honest, I don't understand why do you do random select and insert users only one by one.
In case you want to get only one and random user, just run this query after you've already created views mentioned upper:
SELECT * FROM v_agreeUsers ORDER BY RAND() LIMIT 1
SELECT * FROM v_disagreeUsers ORDER BY RAND() LIMIT 1
Good luck! :)

MySQL query from a query result in php

How should I go if I wanted to query a query result in php?
Supose I have this..
$result = mysql_query("SELECT * FROM tbl_x WHERE tbl_x.attribute = y");
And now I need to query that $result to filter the results I got from its query. Note that I don't want to do this...
$result2 = mysql_query("SELECT * FROM ( SELECT * FROM tbl_x WHERE tbl_x.attribute = y ) AS tbl_x1 WHERE tbl_x1... etc");
The reason I want to avoid that is I'm getting a "Duplicate column" error when executing a query like that.
I'm looking for something like...
$result = mysql_query("SELECT * FROM tbl_x");
$result2 = mysql_query_result($result);
You can apply more than one term in your search conditions, separated by AND:
$result = mysql_query("SELECT * FROM tbl_x
WHERE tbl_x.attribute = y
AND tbl_x.attribute2 = z");
Re your comments above. It sounds like you are using the Entity-Attribute-Value design.
In order to match multiple attributes, you have to do some tricks. Normally, a WHERE clause can only apply to one row at a time. But since each of your attributes are stored on separate rows, you need to do either one of two solutions:
Join multiple rows into one row, so you can use WHERE on all attributes in one condition.
SELECT config_id
FROM attributes AS s
JOIN attributes AS c USING (config_id)
JOIN attributes AS l USING (config_id)
WHERE (s.attr, s.value) = ('size', 'M')
AND (c.attr, c.value) = ('colour, 'green')
AND (l.attr, l.value) = ('cloth', 'cotton);
Search for any of the several attributes, and then if the number of rows that match is equal to the number of attributes you were searching for, you've found them all.
SELECT config_id
FROM attributes
WHERE (attr, value) = ('size', 'M')
OR (attr, value) = ('colour', 'green')
OR (attr, value) = ('cloth', 'cotton')
GROUP BY config_id
HAVING COUNT(DISTINCT attr) = 3;
You can still have your query of query without getting "duplicate column" error. Just alias and name the columns
$result2 = mysql_query("SELECT tbl_x1.col1, tbl_x1.col2,...etc FROM
(SELECT * FROM tbl_x WHERE tbl_x.attribute = y) AS tbl_x1
WHERE tbl_x1... etc");

php sql multiple queries into one

Part of my page I have lots of small little queries, probably about 6 altogether, grabbing data from different tables. As an example:
$sql_result = mysql_query("SELECT * FROM votes WHERE voted_on='$p_id' AND vote=1", $db);
$votes_up = mysql_num_rows($sql_result);
$sql_result = mysql_query("SELECT * FROM votes WHERE voted_on='$p_id' AND vote=0", $db);
$votes_down = mysql_num_rows($sql_result);
$sql_result = mysql_query("SELECT * FROM kids WHERE (mother_id='$p_id' OR father_id='$p_id')", $db);
$kids = mysql_num_rows($sql_result);
Would it be better if these were all grabbed in one query to save trips to the database? One query is better than 6 isn't it?
Would it be some kind of JOIN or UNION?
Its not about number of queries but amount of useful datas you transfer. If you are running database on localhost, is better to let sql engine to solve queries instead computing results in additional programs. The same if you are thinking about who should be more bussy. Apache or mysql :)
Of course you can use some conditions:
SELECT catName,
SUM(IF(titles.langID=1, 1, 0)) AS english,
SUM(IF(titles.langID=2, 1, 0)) AS deutsch,
SUM(IF(titles.langID=3, 1, 0)) AS svensk,
SUM(IF(titles.langID=4, 1, 0)) AS norsk,
COUNT(*)
FROM titles, categories, languages
WHERE titles.catID = categories.catID
AND titles.langID = languages.
example used from MYSQL Bible :)
If you really want to lower the number of queries, you can put the first two together like this:
$sql_result = mysql_query("SELECT * FROM votes WHERE voted_on='$p_id'", $db);
while ($row = mysql_fetch_array($sql_result))
{
extract($row);
if ($vote=='0') ++$votes_up; else ++$votes_down;
}
The idea of joining tables is that these tables are expected to have something in between (a relation, for example).
Same is for the UNION SELECTS, which are prefered to be avoided.
If you want your solution to be clean and scalable in future, I suggest you to use mysqli, instead of mysql module of PHP.
Refer to: mysqli::multi_query. There is OOP variant, where you create mysqli object and call the function as method.
Then, your query should look like:
// I use ; as the default separator of queries, but it might be different in your case.
// The above could be set with sql statement: DELIMITER ;
$query = "
SELECT * FROM votes WHERE voted_on='$p_id' AND vote=1;
SELECT * FROM votes WHERE voted_on='$p_id' AND vote=0;
SELECT * FROM kids WHERE (mother_id='$p_id' OR father_id='$p_id');
";
$results = mysqli_multi_query($db, $query); // Returns an array of results
Fewer queries are (generally, not always) better, but it's also about keeping your code clear enough that others can understand the query. For example, in the code you provided, keep the first two together, and leave the last one separate.
$sql_result = mysql_query("SELECT vote, COUNT(*) AS vote_count
FROM votes
WHERE voted_on='$p_id'
GROUP BY vote", $db);
The above will return to you two rows, each containing the vote value (0 or 1) and the vote count for the value.

What is the query statement to write in order to solve the followin database problem?

I have the following 3 tables in the database.
Programs_Table
Program_ID (Primary Key)
Start_Date
End_Date
IsCompleted
IsGoalsMet
Program_type_ID
Programs_Type_Table(different types of programs, supports a dropdown list in the form)
Program_type_ID (Primary Key)
Program_name
Program_description
Client_Program_Table
Client_ID (primary key)
Program_ID (primary key)
What is the best way to find out how many clients are in a specific program (program type)?
Would the following SQL statement be the best way, or even plausible?
SELECT Client_ID FROM Client_Program_Table
INNER JOIN Programs_Table
ON Client_Program_Table.Program_ID = Programs_Table.Program_ID
WHERE Programs_Table.Program_type_ID = "x"
where "x" is the Program_type_ID of the specific program we're interested in.
OR is the following a better way?
$result = mysql_query("SELECT Program_ID FROM Programs_Table
WHERE Program_type_ID = 'x'");
$row = mysql_fetch_assoc($result);
$ProgramID = $row['Program_ID'];
$result = mysql_query("SELECT * FROM Client_Program_Table
WHERE Program_ID = '$ProgramID'");
mysql_num_rows($result) // returns how many rows of clients we pulled.
Thank you in advance, please excuse my inexperience and any mistakes that I've made.
Here is how you can do it:
<?php
// always initialize a variable
$number_of_clients = 0;
// escape the string which will go in an SQL query
// to protect yourself from SQL injection
$program_type_id = mysql_real_escape_string('x');
// build a query, which will count how many clients
// belong to that program and put the value on the temporary colum "num_clients"
$query = "SELECT COUNT(*) `num_clients` FROM `Client_Program_Table` `cpt`
INNER JOIN `Programs_Table` `pt`
ON `cpt`.`Program_ID` = `pt`.`Program_ID`
AND `pt`.`Program_type_ID` = '$program_type_id'";
// execute the query
$result = mysql_query($query);
// check if the query executed correctly
// and returned at least a record
if(is_resource($result) && mysql_num_rows($result) > 0){
// turn the query result into an associative array
$row = mysql_fetch_assoc($result);
// get the value of the "num_clients" temporary created column
// and typecast it to an intiger so you can always be safe to use it later on
$number_of_clients = (int) $row['num_clients'];
} else{
// query did not return a record, so we have no clients on that program
$number_of_clients = 0;
}
?>
If you want to know how many clients are involved in a program, you'd rather want to use COUNT( * ). MySQL (with MyISAM) and SQL Server have a fast way to retrieve the total number of lines. Using a SELECT(*), then mysql_num_rows leads to unnecessary memory ressources and computing time. To me, this is the fastest, though not the "cleanest" way to write the query you want:
SELECT
COUNT(*)
FROM
Client_Program_Table
WHERE
Program_ID IN
(
SELECT
Program_ID
FROM
Programs_Table
WHERE
Program_type_ID = 'azerty'
)
Why is that?
Using JOIN make queries more readable, but subqueries often prove to be computed faster.
This returns a count of the clients in a specific program type (x):
SELECT COUNT(cpt.Client_ID), cpt.Program_ID
FROM Client_Program_Table cpt
INNER JOIN Programs_Table pt ON cpt.Program_ID=pt.Program_ID
WHERE pt.Program_type_ID = "x"
GROUP BY cpt.Program_ID

SELECT a few rows out of MYSQL

I need to select category ids from my sql database.
I have a variable $product_id and for each product id there are three rows in a table that i need to select using PHP.
If I do "SELECT * FROM table_name WHERE product_id='$prodid'"; I only get the one on the top.
How can I select all three category_ids which contain the same product_id?
I suppose you are using PHP's mysql functions, is this correct? I am figuring that your query is actually returning all three rows but you aren't fetching all of them.
$sql = "SELECT * FROM table_name WHERE product_id='$prodid'";
$r = mysql_query($sql, $conn); //where $conn is your connection
$x = mysql_fetch_SOMETHING($r); //where something is array, assoc, object, etc.
The fetch function gives only one row at a time. You say you need three so it needs to be executed three times.
$x[0] = mysql_fetch_assoc($r);
$x[1] = mysql_fetch_assoc($r);
$x[2] = mysql_fetch_assoc($r);
OR this would be better
while($curRow = mysql_fetch_assoc($r)) //this returns false when its out of rows, returns false
{
$categoryIds[] = $curRow['category_id'];
}
If this doesn't do it then your query is actually returning only one row and we need to see your tables/fields and maybe sample data.
SQL seems to be correct, but Why do you store product_id in categories table? if it's one-to-many relation it would be better to store only category_id in products table.
The SQL query is correct for what you want to do. It will select all the records in table_name with the field product_id = $prodid (not only 1 or 3 but any that matches the variable)
To select a few records you should use the LIMIT keyword
You should look inside your table structure and the variable $prodid to find problems.

Categories