How to merge two UPDATE queries into one, different WHERE and SET? - php

I was wondering if it's possible to combine these two queries as they do not work separately (one of the two only works). They are
$addquery = "UPDATE winners SET mem_name='$addname' WHERE mem_name='$deletename'";
$addresult= mysqli_query($connect, $addquery);
$query = "UPDATE winners INNER JOIN members SET winners.mem_id = members.mem_id
WHERE winners.mem_name = members.mem_name";
$result = mysqli_query($connect, $query);
Can this be done in just one query? Thank you!!!

I am not saying you should do it, but judging from the flow of the code you provided, this is how you could do it.
UPDATE winners w
SET w.mem_name = '$addname'
, w.mem_id = IFNULL(SELECT m.mem_id
FROM members AS m
WHERE m.mem_name = '$addname'
ORDER BY m.mem_id DESC
LIMIT 1
, w.mem_id
)
WHERE w.mem_name = '$deletename'
;
Note, the ORDER BY is technically optional; your question does not state whether mem_name is guaranteed unique in members. If it is unique, the order by should not be needed; if it is not, it at least adds some consistency to the expected value retrieved.
If you have control over the database design, I would suggest removing mem_name from winners altogether. It is/would be redundant data if you were managing the relation primarily by mem_id to begin with.

Related

Fetch data based on another MySQL query

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)?

Reorder ids to be sequential

I have ids separated like 2,3,12,22,23,24, because of adding and deleting items.
So I want to reorder them starting in 1 and set each item sequentially then set auto_increment to the last of them + 1.
I've read similar questions, but no one said why they want this, well I need this because if the ids reach the limit number (255) I won't be able to add more items in the table, and it's ridiculous because there will be like just 30 items in it.
This is probably either easy or I'm missing something, please help me.
As stated in the comments, here's my workaround for your situation (forgive the ugly hacky way to return array key 0.
This is also assuming you're using MySQLi and have already connected to the database
<?php
$query = mysqli_query($con, "SELECT `t1`.`id` + 1 FROM `grpgusers` AS `t1` WHERE NOT EXISTS (SELECT * FROM `grpgusers` AS `t2` WHERE `t2`.`id` = `t1`.`id` + 1) LIMIT 1");
$getID = mysqli_data_seek($query, 0);
$temp = mysql_fetch_array($query);
$id = $temp[0];
Then, on your insert query, add in the new $id.
For example:
mysqli_query($con, "INSERT INTOitems(name,etc.) VALUES ('{escaped postdata}', 'etc.')");
Should then be changed to:
mysqli_query($con, "INSERT INTOitems(id,name,etc.) VALUES (".$id.", '{escaped postdata}', 'etc.')");

Best way to compare the result of a pdo query

I have the following code that works and does what I want it to but I feel I'm using more code than is necessary. All I want to do is get the value in a database cell and check if it is '1' and if so run another query.
$isComplete = $database -> prepare("SELECT completed FROM projects WHERE id = $project_id");
$isComplete -> execute();
$result = $isComplete -> fetchAll();
$result = count($result);
if($result == 1) { $database -> exec("UPDATE projects SET num_complete = num_complete - 1 WHERE id = $parent_id"); }
First, your code is indeed non optimal from the amount of code point of view.
It is also contradicts with your own description
And - worse of all - it is prone to SQL injection.
Also, your variable naming is inconsistent and confusing.
Here is the proper code to check if selected value = 1.
$stmt = $database->prepare("SELECT completed FROM projects WHERE id = ?");
$stmt->execute(array($project_id));
$isComplete = $stmt->fetchColumn();
if ($isComplete) ...
However, I doubt you need such a code at all. To get the number of completed subtasks is a matter of one simple query. Are you really sure you need this num_complete field at all?
Instead of a subquery in the WHERE clause, you can put one in a JOIN clause to get around MySQL's limitation against targeting a table both in an UPDATE and a subquery. Also, instead of selecting all rows with a given project ID and counting them in PHP, you can perform the calculation in the SQL query. Something like:
UPDATE projects p0
JOIN (SELECT id, count(*) AS nSiblings
FROM projects
WHERE id=:project GROUP BY id)
AS p1
ON p0.id=p1.id
SET p0.num_complete=p0.num_complete+1
WHERE p1.nSiblings=1
Note that since it's an inner join, specifying the ID in the subquery is sufficient. You could also probably drop the GROUP BY id, but if you ever adapt the statement for another use, it could introduce a bug.
There may be other issues with the table design that affect this query (and other aspects), but since no schema was provided, there's no way to provide feedback.
You can use a subquery to check the condition in the update statement. Something like this:
UPDATE projects SET num_complete = num_complete - 1 WHERE id = $parent_id
and (select completed from projects where id = $project_id) = 1
For example:
$st = $database->prepare("UPDATE projects SET num_complete = num_complete - 1 WHERE id = :parent_id
and (select completed from projects where id = :project_id) = 1");
$st->bindParam(':parent_id', $parent_id, PDO::PARAM_INT);
$st->bindParam(':project_id', $project_id, PDO::PARAM_INT);
$st->execute();

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

Categories