Priority Row Increase or Decrease based on Selection - php

I have searched and searched but can't find what I'm after, it's probably super simple.
I have a table that has a priority field to display in order that was chosen. What I want to be able to do I have seen but don't know how to make my code do it.
Take data with priority 1,2,3,4,5,6 and change #5 to 4 and adjust all the other numbers accordingly.
So now it would be 1,2,3,4 (old 5),5 (old 4),6.
I'm using PHP, Mysql and for some reason I'm not getting this concept. I can increase/decrease the number but I can't adjust the others around it. So I end up with 1,2,3,4,4,6
Table structure
ID, Cat, Title, Priority
I only want to increase/decrease in the cat. I'm looking at sorting multiple at a time so it could be
1 (old 5), 2 (old 3), 3 (old 6)... etc
Thanks for the help.
EDIT
Maybe my first explaination wasn't explained well enough.
Let's say I have 10 pictures, each with a unique ID and the priority they are given right now is the same as the ID. I can display the images ORDER BY priority
ID 1,2,3,4,5,6,7,8,,9,10
Priority 1,2,3,4,5,6,7,8,9,10
But after looking at the pictures I want to change the priority they are shown.
SO... I click an arrow that has a link that tells the database to update picture ID 4 with priority 4 to be ID 4 priority 2 because it's more important.
Now my database looks like this.
ID 1,2,3,4,5,6,7,8,9,10
Priority 1,2,2,3,5,6,7,8,9,10 because the rest of the priority numbers didn't get changed because I don't know how to make that work.
What I want to do is, after I change one priority to the new one, rearrange the numbers so they are in numerical order after that number because they are less important. How do I do this?

I hope this following code could give you som help how to solve your problem/challenge.:
<?php
//Say that you've recieved array from db...
$arr = array();
$arr[0] = array('id'=>5, 'sortOrder' => 1, 'picture' => 'picture1');
$arr[1] = array('id'=>6, 'sortOrder' => 2, 'picture' => 'picture2');
$arr[2] = array('id'=>7, 'sortOrder' => 3, 'picture' => 'picture3');
$arr[3] = array('id'=>9, 'sortOrder' => 4, 'picture' => 'picture4');
$arr[4] = array('id'=>10, 'sortOrder' => 5, 'picture' => 'picture5');
//Do some sorting...
$executeSQL = down($arr,2); //Tell sortOrder to decrease for picture3 and to increase for picture2
//Array will change to:
//$arr[1] = array('id'>=6, 'sortOrder' => 3, 'picture' => 'picture2');
//$arr[2] = array('id'>=7, 'sortOrder' => 2, 'picture' => 'picture3');
//$executeSQL returns an array of two sql-statements that you should execute
$executeSQL = up($arr, 1); //Decrease sortorder for picture2 and increase for picture3
//Array will change to:
//$arr[1] = array('id'=>6, 'sortOrder' => 2, 'picture' => 'picture2');
//$arr[2] = array('id'=>7, 'sortOrder' => 3, 'picture' => 'picture3');
//$executeSQL returns an array of two sql-statements that you should execute
echo print_r($arr,true); //Will output the original array
function down(Array &$arr, $index) {
$origPrev = $arr[$index-1]['sortOrder'];
$arr[$index-1]['sortOrder'] = $arr[$index]['sortOrder'];
$arr[$index]['sortOrder'] = $origPrev;
$sql = "UPDATE table SET sortOrder=" . $origPrev . " WHERE id=" . $arr[$index]['id'];
$sql2 = "UPDATE table SET sortOrder=" . $arr[$index]['sortOrder'] . " WHERE id=" . $arr[$index-1]['id'];
return array($sql, $sql2);
}
function up(Array &$arr, $index) {
$origPrev = $arr[$index+1]['sortOrder'];
$arr[$index+1]['sortOrder'] = $arr[$index]['sortOrder'];
$arr[$index]['sortOrder'] = $origPrev;
$sql = "UPDATE table SET sortOrder=" . $origPrev . " WHERE id=" . $arr[$index]['id'];
$sql2 = "UPDATE table SET sortOrder=" . $arr[$index]['sortOrder'] . " WHERE id=" . $arr[$index+1]['id'];
return array($sql, $sql2);
}
?>

Related

PHP/MYSQL - Counting and comparing entries in a myqsl table with php

I was wondering if anybody can help me out/point me in the right direction.
I have a database with a table that includes incremental id, name, unique id, and the parent uuid of fictional characters.
The table shows the following people...
John (Parent not listed)
Steve (Parent listed as John)
Mark (Parent listed as John)
Kevin (Parent listed as Steve)
Adam (Parent listed as Mark)
**ID, NAME, UUID, PARENT_UUID**
1, John, 0001, none
2, Steve, 0002, 0001
3, Mark, 0003, 0001
4, Kevin, 0004, 0002
5, Adam, 0005, 0003
So in this example, John has 2 sons, Steve and Mark... each of whome have a son, Kevin and Adam.
What I want to do, is (on an already made profile page) show the number of family members.
So going to Johns page, I would see "John (4 Descendents)", and if I went to Marks page, I'd see "Mark (1 Descendents)"
Allowing me to list how many family members, in lower generations are found in the table.
I am able to print a list of all family members... using:
$sql = "SELECT * FROM users";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
echo $row["uuid"]. "<br>";
}
}
But now I want to find out for each $row['uuid'] how many descendents each entry has.
I tried doing something like the following:
$sql = "SELECT * FROM users";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$sql = "SELECT * FROM users WHERE parent_uuid = '".$row['uuid']."'";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
$numOfDescendents = $result->num_rows;
}
}
}
But then I realised that not only does this not work (it grabs the number of the first row and stops), that using this logic, if I have a family with 20+ generations, I'm going to need to have 20+ while loops nested within each other, checking each generation.
So I'm wondering, is this even possible?
There's probably an easy way, but after 3/4 days of headaches and frustration I'm finally asking for help =)
My end goal is to have a php file that checks through the table for all users, and totals their descendents by counting how many people in the table use their uuid as a parent_uuid... as in the example at the start... John would have 4, Mark would have 1, Steve would have 1, Kevin would have 0, and Adam would have 0.
Thanks in advance for any guidance =)
You can use a recursive function to solve this. Note - I am passing the entire input to the recursive array which I do not recommend. If you are using a class set the input as a property of the class or you can use global which is also not recommended.
$input = [
['id' => 1, 'name' => 'John', 'UUID' => 0001, 'PARENT_UUID' => null],
['id' => 2, 'name' => 'Steve', 'UUID' => 0002, 'PARENT_UUID' => 0001],
['id' => 3, 'name' => 'Mark', 'UUID' => 0003, 'PARENT_UUID' => 0001],
['id' => 4, 'name' => 'Kevin', 'UUID' => 0004, 'PARENT_UUID' => 0002],
['id' => 5, 'name' => 'Adam', 'UUID' => 0005, 'PARENT_UUID' => 0003],
];
function getDescendents($uuid, $input, $count = 0, $descendants = [])
{
foreach ($input as $user) {
if ($user['PARENT_UUID'] === $uuid) {
$count++;
$descendants[] = $user['UUID'];
}
}
if (!empty($descendants)) {
$new_uuid = array_shift($descendants);
return getDescendents($new_uuid, $input, $count, $descendants);
}
return $count;
}
$result = [];
foreach ($input as $user) {
$result[$user['name']] = getDescendents($user['UUID'], $input);
}
echo(json_encode($result));
Output -
{"John":4,"Steve":1,"Mark":1,"Kevin":0,"Adam":0}
The key in the above object is the user's name and the value is the number of descendants.

Trying to merge two results of SQL queries - ToDoList App

I am trying to merge two results of two queries in MYSQL using PHP, but I am puzzled how to do it! I am using PDO. I am programming for a hobby and am trying to make a to do list app just like a Trello board. However, I just can't figure out how to merge two results from different tables in a database.
The idea is as follows:
I have a table called 'task_lists' with the content:
'list_id => 1, list_name = 'listOne'
'list_id => 2, list_name = 'listTwo'
And a table called 'tasks':
task_id => 1, list_id => 1, task_name => 'taskOfListOne', duration => 5, is_done => 1
task_id => 2, list_id => 1, task_name => 'anotherTaskOfListOne', duration => 5, is_done => 1
task_id => 3, list_id => 2, task_name => 'taskOfListTwo', duration => 10, is_done => 0
And I am trying to create an array that is merged between the two results as something like:
(I know this is a rough picture of how the array is supposed to look like)
$result = [array]
[list_id] = 1, [list_name] = 'listOne' =>
[array][list_id] = 1, ['task_name] = taskOfListOne,[duration] = 5, ['is_done'] => 1
[array][list_id] = 1, ['task_name] = anotherTaskOfListOne,[duration] = 5, ['is_done'] => 1
[list_id] = 2, [list_name] = 'listTwo' =>
[array][list_id] = 2, ['task_name] = taskOfListTwo,[duration] = 5, ['is_done'] => 1
Is this even possible? I have tried a Union sql query and methods like nested foreach statements, but none of them worked for me. Am I missing something here?
PS: Sorry for my bad english.
Have you tried a left join?
SELECT TL.`list_id`, TL.`list_name`, T.`task_name`, T.`duration`
FROM task_lists AS TL
LEFT JOIN tasks as T ON TL.`list_id` = T.`list_id`
And then in PHP you build the array in the format you want.
Later edit:
Simple PHP example to parse SQL data as you asked (to remove duplicated info):
<?php
// $mysql_rows -> here is your query result, fetched as associative array
$filtered_array = array();
foreach ($mysql_rows as $row){
// Initiate record if is not already initiated
if (!isset($filtered_array[ $row['list_id'] ])){
$filtered_array[ $row['list_id'] ] = array(
'list_id' => $row['list_id'],
'list_name' => $row['list_name'],
'tasks' => array()
);
}
// Add tasks
$filtered_array[ $row['list_id'] ]['tasks'][] = array(
'task_name' => $row['task_name'],
'duration' => $row['duration'],
'is_done ' => $row['is_done ']
);
}
// Optional: if you want to remove list_id from $filtered_array key names, uncomment the next line
// $filtered_array = array_values($filtered_array);
?>

How to LIMIT a Query which is already been selected?

I am trying to LIMIT a Query which is already been selected. I know I can directly do it in my query select, but due to some logics of the code, if I do that way I have to run the query selection twice which (I believe) will increase the computational time!
So, what I am trying is this:
$query1 = $mysqli->query("SELECT * FROM tableName WHERE someconditions");
then, I need to re-select a sub-selection of the $query1 for my Pagination. What I am trying to do is something like this;
$query2 = LIMIT($query1, $limit_bigin, $limit_end);
where $limit_bigin, $limit_end provide the LIMITING range (start and end respectively).
Could someone please let me know how I could do this?
P.S. I know I can do it directly by:
$query1 = $mysqli->query("SELECT * FROM tableName WHERE someconditions");
$query2 = $mysqli->query("SELECT * FROM tableName WHERE someConditions LIMIT $limit_bigin, $limit_end");
But this is running the query twice and slows down the process (I must run the first query without limits due to some logics of the program)
EDIT 1
As per the answers I tried using array_slice in PHP. BUT, since Query is an object it doesn't give the results that was expected. A NULL is resulted form
array_slice($query1, $start, $length, FALSE)
If you have already carried out the query and the result set has been returned to your PHP, you can not then LIMIT it. As you state, then running a second SQL execution of a subpart of the same query is wasteful and repetative.
Don't
Repeat
Yourself.
DRY.
As I said above, repetition causes issues with maintainability as you can easily forget about repetition, tweaking one SQL and forgetting to tweak the other.
Don't
Repeat
Yourself.
DRY.
Use PHP instead
Once you have executed the query, the result set is then passed back to PHP.
So assuming you have a $var with the contents of you SQL query, then you simply need to select the valid rows from the $var, not from the database [again].
You can do this using PHP numerous Array functions. Particularly array_slice().
So;
$query1 = $mysqli->query("SELECT * FROM tableName WHERE someconditions");
Now, to select the second page, say for example rows 10 to 20:
$query2 = array_slice($query1, (10-1), 10 );
This wil then "slice" the part of the array you want. Remember that the array counts will start at zero so to grab row 10 (of an index starting at 1, Typical of a MySQL Auto Increment Primary Key), then you will need to select X number of rows from row (10-1) .
Please also read the manual for PHP array_slice().
Further
As referenced in comments, there is no guarentee that your SQL will return the same values each time in the same order, so it is highly recommended to order your results:
$query1 = $mysqli->query("SELECT * FROM tableName
WHERE someconditions ORDER BY primary_key_column");
Example Data:
$query1 = $mysqli->query("SELECT * FROM tableName WHERE someconditions ORDER BY id");
/***
$query1 = array {
0 => array { 'id' => 1, 'user' => "Jim", 'colour' => "Blue" },
1 => array { 'id' => 2, 'user' => "Bob", 'colour' => "Green" },
2 => array { 'id' => 3, 'user' => "Tom", 'colour' => "Orange" },
3 => array { 'id' => 4, 'user' => "Tim", 'colour' => "Yellow" },
4 => array { 'id' => 5, 'user' => "Lee", 'colour' => "Red" },
5 => array { 'id' => 6, 'user' => "Amy", 'colour' => "Black" }
}
***/
$page = 2;
$size = 3; // number per page.
$start = ($page - 1) * $size; //page number x number per page.
// Select the second page of 3 results.
$query2 = array_slice($query1, $start, $size , FALSE);
/***
$query2 = array {
0 => array { 'id' => 4, 'user' => "Tim", 'colour' => "Yellow" },
1 => array { 'id' => 5, 'user' => "Lee", 'colour' => "Red" },
2 => array { 'id' => 6, 'user' => "Amy", 'colour' => "Black" }
}
***/
You can then use these in a foreach or other standard array manipulation technique.

Filtering out multiple records in dataset

I'm working with a dataset coming back from a very complex view with multiple subselects and joins against several tables in a very large and convoluted database.
Each record has a structure like this:
MainValue = XXTS10, qtyPlaceholder1, qtyPlaceholder2, qtyPlaceholder3..., actualQty = 3, qtyPlaceholderKey = 1, color = blue.
MainValue = XXTS10, qtyPlaceholder1, qtyPlaceholder2, qtyPlaceholder3..., actualQty = 10, qtyPlaceholderKey = 3, color = blue.
MainValue = XXTS10, qtyPlaceholder1, qtyPlaceholder2, qtyPlaceholder3..., actualQty = 9, qtyPlaceholderKey = 2, color = blue.
So for each color and MainValue values, there are multiple records. I need to set the value of each qtyPlaceholder based on the actualQty where the qtyPlaceholderKey will tell me what value to put in each and derive only one record out of many so that the final single record looks like this:
MainValue = XXTS10, qtyPlaceholder1 = 3, qtyPlaceholder2 = 9, qtyPlaceholder3 = 10, color = blue.
I know I've done this hundreds of times over the years, but I'm just having mental block creating the proper looping structure and conditionals to create a single record out of many with the values mapped to the placeholders correctly. Trying to accomplish this in PHP, but it may be a good idea to reexamine the view and see if it can be adjusted, but I really don't want to go down that path if I can help it.
Any suggestions?
You can do this in SQL using conditional aggregation. Here is a select form of the query:
select MainValue,
max(case when qtyPlaceholderKey = 1 then actualQty end) as qtyPlaceholder1,
max(case when qtyPlaceholderKey = 2 then actualQty end) as qtyPlaceholder2,
max(case when qtyPlaceholderKey = 3 then actualQty end) as qtyPlaceholder3,
color
from complexview v
group by MainValue, color;
Loop through your array and create a new array indexed by
MainValue
color
qtyPlaceholderKey with a value of actualValue
Then 'flatten' the new array by looping through the new array and assigning key value pairs for MainValue, color and all qtyPlaceholderKeys and their corresponding actualValues.
$dbrows = array(
array(
'MainValue' => 'XXTS10',
'actualQty' => 3,
'qtyPlaceholderKey' => 1,
'color' => 'blue',
),
array(
'MainValue' => 'XXTS10',
'actualQty' => 9,
'qtyPlaceholderKey' => 2,
'color' => 'blue',
),
array(
'MainValue' => 'XXTS10',
'actualQty' => 10,
'qtyPlaceholderKey' => 3,
'color' => 'blue',
),
);
$values = array();
foreach($dbrows as $r) {
$values[$r['MainValue']][$r['color']][$r['qtyPlaceholderKey']] = $r['actualQty'];
}
$result = array();
foreach($values as $mainValue => $colorValues) {
foreach($colorValues as $color => $qtyPlaceholderValues) {
$row = array('MainValue' => $mainValue, 'color' => $color);
foreach($qtyPlaceholderValues as $qtyPlaceholderKey => $actualQty) {
$row["qtyPlaceholderKey$qtyPlaceholderKey"] = $actualQty;
}
$result[] = $row;
}
}
print_r($result);
Demo

Using supplier with largest margin using PHP logic

I have the following values from a database call that I want to apply some logic to. I thought I could originally use PHP's max however this doesn't appear to be the case.
I have three suppliers of a product. They might not all stock the item I am displaying, and they all offer a different margin, on a product by product basis though, so that is why I can't just say generally supplier 1 is better than supplier 2 etc.
$supplier1Live = 1
$supplier2Live = 1
$supplier3Live = 0
$marginSupplier1 = 20
$marginSupplier2 = 40
$martinSupplier3 = 50
In this example I would want to use Supplier 2 as they stock the product supplier2Live = 1 and also have the better margin than the other supplier who stocks the product (supplier1)
My mind however is drawing a complete blank in how to code this?
I thought I could add it to an array giving:
$array = array(
"supplier1" => array(
"live" => 1,
"margin" => 20
),
"supplier2" => array(
"live" => 1,
"margin" => 40
),
"supplier3" => array(
"live" => 0,
"margin" => 50
)
);
And run something on that, but not sure what to.
Filter the array using array_filter (filter by live==1), and then find the maximum out of the resultant array (maximum on the "margin" value)
Like this, if I understand correctly
$array = array(
"supplier1" => array(
"live" => 1,
"margin" => 20
),
"supplier2" => array(
"live" => 1,
"margin" => 40
),
"supplier3" => array(
"live" => 0,
"margin" => 50
)
);
$res = array_filter($array,function($v){return $v["live"];});
$supplier = array_reduce($res, function($a, $b){
return $a["margin"]>$b["margin"]?$a:$b;
});
print_r($supplier);
Try something like this:
$best_supplier = null;
$best_supplier_margin = null;
foreach($array as $name => $supplier) {
if($supplier['live']) {
if($supplier['margin'] > $best_supplier_margin || is_null($best_supplier_margin)) {
$best_supplier = $name;
$best_supplier_margin = $supplier['margin'];
}
}
}
if(is_null($best_supplier)) throw new Exception('No suppliers are live!');
echo $best_supplier;
So you basically want to find the max of supplierXLive * marginSupplierX?
You can also implement a custom compare function and provide it to PHPs usort() function

Categories