drag & drop saving to mysql optimalized - php

There have been a few similar problems here on SO, but I had already implemented my way; Thought this is far from what would be expected "good"; The problem is that I have a list, you can drag & drop, though if one drags 1 element from position to position 50, 49 elements need to get updated (this would be 49 queries) just to save 1 action; Now to not do this, I saved a list and save the list to mysql;
+---------+------------+-----------+
| user_id | project_id | user_sort |
+---------+------------+-----------+
| 1 | 2 | 3,1,2 |
+---------+------------+-----------+
This has the advantage, I only need to update 1 line; The issue however is when user returns, I need to do 2 queries (select user_sort, and select all id's); and use PHP in between to explode(user_sort); most unclean and prolly slow.
Is there a better way to do this ?

if one drags 1 element from position to position 50, 49 elements need
to get updated (this would be 49 queries) just to save 1 action
That is not true, you can update all 49 rows in 2 queries:
$id = 10; // moved element
$old_pos = 1;
$new_pos = 50;
// elements between old and new position
if ($new_pos > $old_pos) {
$sql1 = "
UPDATE my_table
SET user_sort=user_sort-1
WHERE user_sort > $old_pos
AND user_sort <= $new_pos";
} else {
$sql1 = "
UPDATE my_table
SET user_sort=user_sort+1
WHERE user_sort >= $old_pos
AND user_sort < $new_pos";
}
// moved element
$sql2 = "UPDATE my_table SET user_sort=$new_pos WHERE id=$id";

Related

How can i get one id result and add it to another in a mysql table?

How can I record all data in a table together?
i have values in individual rows that i wish to add up to one. and get the value into a variable.
what can i use instead of this code below to get all id in the table instead of one?
if(isset($_GET['ide'])){
$coode = $_GET['ide'];
so that once i get all id, i can do the query below...
$products = $db->query("SELECT e1,e2 FROM eyfstb WHERE specialnum='$coode'");
while($row = $products->fetch_assoc()){
$e1view = $row["e1"]; $e2view = $row["e2"];
}
and once the query is done, i want to be able to store them in a variable like below
$final = (e1,e2 of id1) + (e1,e2 of id2) + (e1,e2 of id3) + (e1,e2 of id4);
fine is 5
good is 4
fair is 3
my e1 is fine which is equal 5
my e2 is good which is equal 4
making 9 when i added it.
but i want to get for all record rows in the table
currently i'm able to get the details for only one student from the url $coode but i want to get for all the student from a table and be able to add the resulting data.
Table Structure
id | e1 | e2 |
---------------------------
1 | fine | good |
2 | good | good |
3 | fair | fine |
Better way is to store in database parameters like this as integer. It generates less problems with math operations or comparison.
But if you can't refactor it you should map each value to their numerical equivalent.
function mapDbValue(string $value): int {
switch ($value) {
case 'fine': return 5;
case 'good': return 4;
case 'fair': return 3;
}
}
And now in your while loop map values and add it.
$final = 0;
while (...) {
$final += mapDbValue($row['e1']) + mapDbValue($row['e2']);
}

SQL Query get row rank or position on the main select query

I'm trying to get the Rank of a specific row from my SELECT query.
Here's my table :
| PID | Age |
|------ |----- |
| 5295 | 27 |
| 4217 | 26 |
| 2935 | 25 |
| 8706 | 24 |
My query and code: I'm using SQL Server
$x = 0;
$query = odbc_exec($connect, "SELECT * FROM mytable ORDER BY Age DESC"); // Ordering by "Age" Descending
while($row = odbc_fetch_array($query)) {
$x++;
if($row['PID'] == 2935) { break; // Stop }
}
echo $x; // output "3"
This method works, but the question is can this be done with simple standalone SQL Query instead of looping through all results then incrementing $x variable to get the specified row rank. because this table contains thousands of entries which will be a little laggy while looping till it find the desired row then stop looping.
The logic of this ranking since I order with Age descending, so for example it will start with 27 with rank 1 along to 24 with rank 4.
How can I achieve this?
You can use row_number() in a subquery to assign a rank to each record, then filter out in the outer query on the row you are interested in:
select *
from (
select t.*, row_number() over(order by age desc) rn
from mytable t
) t
where pid = 2935
In MySQL, window functions are supported in version 8.0 only. In SQL Server, they have been available for a long time.

How can I get the sums of all the integers in a row of an SQL table with PHP?

I am currently making an attendance website. The data for attendance is stored like this...
+-----------------------------------------------+
| Name | 12/20/16 | 12/21/16 | 12/23/16 |
+-----------------------------------------------+
|Person1 | 1 | 0 | 1 |
|Person2 | 0 | 1 | 0 |
|Person3 | 1 | 1 | 1 |
+-----------------------------------------------+
If a person was there, then the date column for their row is marked as a "1". If they weren't there, then the date column for their row is marked as a "0".
I am trying to make a readout of how many days they were present.
How can I get a sum of all the values in the date columns for that specific person's row in PHP?
EDIT: I understand that it is a bad way of formatting the data. This is per the owners request. They have their mind set on it and won't listen to reason. They are thinking of SQL as an Excel file.
Since you can't refactor the database to work the only way to do this is
SELECT name, `12/20/16`+`12/21/16`+`12/23/16` as days_attended
FROM tablename
and yes every time you add a column you have to change your query.
You could make a dynamic query -- use the above as a template as to what that dynamic query would look like.
But you REALLY should refactor the database and make a view for your user to make them happy.
This is exactly why views exist.
Okay so with the help of some people in the comments, I have put together a working function to accomplish what I needed.
$ppl = mysqli_query($conn, "SELECT * FROM Attendance2016 WHERE name = '" . getSessionVal("Name") . "'");
$row = mysqli_fetch_array($ppl);
$loopMax = count($row);
$currentAtttendance = 0;
for($x = 0; $x < $loopMax; $x++){
if($row[$x] === "0"){
continue;
}else if($row[$x] === "1"){
$currentAtttendance = $currentAtttendance + 1;
}
}
return $currentAtttendance;

Update Mysql: Manager Order Column(no ID) preserve numerical spaces

i am try to update a mysql table with a PHP instance query.
but I do not know how to put the query correctly or whether there is a logical part it works specified side mysql or if i can do with php.
i get the data from a web form with 2 field the ID(It is the autoincrementable ID in MySQL) and a input with the new order.
Update Case 1: Change Order Update Data
ID=3
Imput=5
Original table 1
+--------+---------+
| ID | Order |
+--------+---------+
| 1 | 1 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 10 |this have a Hole from last registre order need preserve
| 8 | 11 |
+--------+---------+
Table
+--------+---------+
| ID | Order |
+--------+---------+
| 1 | 1 |
| 2 | 2 |
| 3 | 5 |Updated
| 4 | 6 |Updated
| 5 | 7 |Updated
| 6 | 8 |Updated
| 7 | 12 |Update, preserve and continue the hole
| 8 | 13 |Update, and Continue if more record
+--------+---------+
Update Case 2: Inserting a new record and modify the order.
ID=2
Imput=4
Original table 2
+--------+---------+
| ID | Order |
+--------+---------+
| 1 | 1 |
| 7 | 10 |this have a Hole from last registre order need preserve
| 8 | 11 |
+--------+---------+
Table
+--------+---------+
| ID | Order |
+--------+---------+
| 1 | 1 |
| 2 | 4 |record Inserted
| 7 | 10 |preserve no need update
| 8 | 11 |
+--------+---------+
I need some cycles, but do not know what conditions apply.
basics sorry for my example but I am not very expert
Update 1 Legancy
<?php
#Get Values from input Dinamical:
# $i_txt_1 = ID
# $i_txt_3 = New Order
# Attention: this is not the correct syntax for PHP, they are guidelines on what to do at every step, and that must be taken into account for the creation of the string of update.
foreach ($_POST as $key => $value){
${$key} = trim(addslashes(strip_tags($value)));
}
#collector output message
$psmg = '';
#statement prepared for the query updater
$stmtpreUP ="";
#save this variable the current date using some specific function.
$DateUD;
#We keep the variable that is the form that represents the ID
$ID = $i_txt_1;
#first condition
1. search the database if the ID exists we receive the form.
result 0{
throw new Exception You can not modify a nonexistent parameter. Search before Change
}
#second condition
2. if order is the same that the current order display MSG
{
$psmg.='<br>Update was not carried out in the Order';
}
#third condition
3. if check if it exists, any record or ID, with the order comes from the form.
result 0{
update: Create a direct update using the new order and id.
}else{
#Important Step : detecting whether an increase or decrease in the order
4. $GViD = $i_txt_3 - order;
if ($GViD < 0){
#in case is decreasing the order
$stmtpreUP .="UPDATE Table SET Order= $i_txt_3, DateUD= DateUD WHERE ID = $i_txt_1"; #String update for the ID target
#Generate the string updater for the following rows, contemplating that, if a decrease in these rows ID target should be avoided.
5.
GET "SELECT ID, Order FROM Table WHERE Order >= ".$i_txt_3." ORDER BY Order ASC";
$count = $i_txt_3; #need a counter
#Cicle to generate Update String
6.
while ($datos = mysqli_fetch_array($Get)){
#condition to ignore the target ID and update only up to the target ID range, avoid overuse of resources
if($datos['ID']!==$ID AND $datos['ID']<$ID ){
$idUD = $datos['ID'];
$count = ++$count;
$neworder = $count;
#concatenation to the Update String
$stmtpreUP .= "UPDATE table SET Order = ".$neworder.", DateUD ='".$DateUD."' WHERE ID ='{$idUD}';";
}
}
}else{
#in case is Increase the order
$stmtpreUP .="UPDATE Table SET Order= $i_txt_3, DateUD= DateUD WHERE ID = $i_txt_1"; #String update for the ID target
#Generate the string updater for the following rows, contemplating that, if a decrease in these rows ID target should be avoided.
7.
GET "SELECT ID, Order FROM Table WHERE Order >= ".$i_txt_3." ORDER BY Order ASC";
$count = $i_txt_3; #need a counter
#Cicle to generate Update String
8.
while ($datos = mysqli_fetch_array($Get)){
#condition to ignore the target ID and update all the next Order for all the table to preserver spaces into order
if($datos['ID']!==$ID){
$idUD = $datos['ID'];
$count = ++$count;
$neworder = $count;
#concatenation to the Update String
$stmtpreUP .= "UPDATE table SET Order = ".$neworder.", DateUD ='".$DateUD."' WHERE ID ='{$idUD}';";
}
}
}
}
#Run the update of all the statement
9. #function to run mutiple statement updates.
BDupdateM($stmtpreUP);
$psmg.='Datos Actualizado Correctamente';
10. output all MSG
echo $psmg;
?>
Why would you want to make something like that man, you are approaching it the wrong way IMO such a thing will be so expensive (performance wise).
If you want to ORDER BY ID, then by Order you just need to make a SELECT statement like
SELECT * FROM table ORDER BY id,order
<?php
#Get Values from input Dinamical:
# $i_txt_1 = ID
# $i_txt_3 = New Order
# Attention: this is not the correct syntax for PHP, they are guidelines on what to do at every step, and that must be taken into account for the creation of the string of update.
foreach ($_POST as $key => $value){
${$key} = trim(addslashes(strip_tags($value)));
}
#collector output message
$psmg = '';
#statement prepared for the query updater
$stmtpreUP ="";
#save this variable the current date using some specific function.
$DateUD;
#We keep the variable that is the form that represents the ID
$ID = $i_txt_1;
#first condition
1. search the database if the ID exists we receive the form.
result 0{
throw new Exception You can not modify a nonexistent parameter. Search before Change
}
#second condition
2. if order is the same that the current order display MSG
{
$psmg.='<br>Update was not carried out in the Order';
}
#third condition
3. if check if it exists, any record or ID, with the order comes from the form.
result 0{
update: Create a direct update using the new order and id.
}else{
#Important Step : detecting whether an increase or decrease in the order
4. $GViD = $i_txt_3 - order;
if ($GViD < 0){
#in case is decreasing the order
$stmtpreUP .="UPDATE Table SET Order= $i_txt_3, DateUD= DateUD WHERE ID = $i_txt_1"; #String update for the ID target
#Generate the string updater for the following rows, contemplating that, if a decrease in these rows ID target should be avoided.
5.
GET "SELECT ID, Order FROM Table WHERE Order >= ".$i_txt_3." ORDER BY Order ASC";
$count = $i_txt_3; #need a counter
#Cicle to generate Update String
6.
while ($datos = mysqli_fetch_array($Get)){
#condition to ignore the target ID and update only up to the target ID range, avoid overuse of resources
if($datos['ID']!==$ID AND $datos['ID']<$ID ){
$idUD = $datos['ID'];
$count = ++$count;
$neworder = $count;
#concatenation to the Update String
$stmtpreUP .= "UPDATE table SET Order = ".$neworder.", DateUD ='".$DateUD."' WHERE ID ='{$idUD}';";
}
}
}else{
#in case is Increase the order
$stmtpreUP .="UPDATE Table SET Order= $i_txt_3, DateUD= DateUD WHERE ID = $i_txt_1"; #String update for the ID target
#Generate the string updater for the following rows, contemplating that, if a decrease in these rows ID target should be avoided.
7.
GET "SELECT ID, Order FROM Table WHERE Order >= ".$i_txt_3." ORDER BY Order ASC";
$count = $i_txt_3; #need a counter
#Cicle to generate Update String
8.
while ($datos = mysqli_fetch_array($Get)){
#condition to ignore the target ID and update all the next Order for all the table to preserver spaces into order
if($datos['ID']!==$ID){
$idUD = $datos['ID'];
$count = ++$count;
$neworder = $count;
#concatenation to the Update String
$stmtpreUP .= "UPDATE table SET Order = ".$neworder.", DateUD ='".$DateUD."' WHERE ID ='{$idUD}';";
}
}
}
}
#Run the update of all the statement
9. #function to run mutiple statement updates.
BDupdateM($stmtpreUP);
$psmg.='Datos Actualizado Correctamente';
10. output all MSG
echo $psmg;
?>

mysql insert into function

I am creating a simple PHP webpage with MySQL database.
The MYSQL database have the following contents: (illustration on left)
I just want to know a possible way of doing some Data Manipulation to achieve the results on the right portion below.
(initial value) (final result)
ID | MINUS '1'(to "next" ID's) ID | ID |
1 | 0 1 | ------------> 1 |
2 | 1 --> (will minus '1' to ID 3 2 | ------------> 2 |
3 | 0 up to the last) 3-1 = 2 | ------------> 2 |
4 | 0 4-1 = 3 | ------------> 3 |
5 | 1 --> (minus '1' AGAIN to ID 6 5-1 = 4 | ------------> 4 |
6 | 0 up to the last) 6-1 = 5 -1 ---> 4 |
7 | 0 7-1 = 6 -1 ---> 5 |
It is just COUNTING the number of minus and then subtracting it to ALL the ID that follows it. ID 2 has tells the next ID, which is 3 to subtract 1 to itself up to the last ID, (3-1 , 4-1, 5-1, 6-1, 7-1 ) but another instance came. ID 5 tells ID 6 to subtract itself again up to the last, so MINUS 2 from ID 6 up to the last ID. from just 6-1, 7-1 ---> 6-2, 7-2.
I know it sounds very easy for you, but I'm just a newbie and find this thing hard. Sorry for the headache. Hope someone helps, Thanks!
my DML is like (just for illustration, this should be in php, I will convert it, just help me in the LOGIC)
for($x=0;$x<num_rows;$x++)
{
if(MINUS = 1){
query(UPDATE table_name SET ID=ID-1 WHERE ID = $x);}
}
Something like that, i am still a newbie in decision making loops. I will be grateful if you could fix my loop. I am new to this community, I beg for your understanding.
You can do this in MySQL either using variables or standard SQL. Here is the standard SQL:
select id, minus,
(id - coalesce((select sum(minus) from table t2 where t2.id < t.id), 0)) as newId
from table t;
Here is the variable version:
select id, minus,
(id - minus + (#value := #value + minus)) as newId
from table t cross join
(select #value = 0) const
order by id
You can use a MySQL implementation as follows:
select id, minus,
(id - coalesce((select sum(minus) from table t2 where t2.id < t.id), 0)) as newId
from table t;
The code idea came from Gordon's post, here is an elaboration.
The first part is select which states that you want to select certain input from mysql. id, minus follows, and means that you want to return the values of id and minus when the query has finished running.
The rest of it falls under the third part, where you perform the subtraction, and return the value of the subtraction as newId. So when the sql returns, it will get a row with ID, MINUS and NEWID as it's headings.
The subtraction works like this: coalesce returns the first non-null value (i.e. 1) in the list. the table t2 is using a second version of the table and calling it t2 so that you can compare information.
I hope this clarified things for you!

Categories