`position` column in database, how to re-order? - php

I have the following table:
id | name | position
1 Bob 4
2 Jim 5
3 Harry 73
4 Paul 89
I want the user to be able to re-order the columns as they see fit, like move one row up and down, using the position column. I have thrown in the big numbers in there (73 and 89) just to cater for all events.
Is there a way to dynamically re-order the table via SQL? Or will I have to manually re-order all tables when someone selects 'move up' on 'Harry'? I can only imagine I will have to:
Find the ID before Harry's (in this case '2')
Move all ID's (including '2's) up by one.
Set Harry's position to to '2'.
There must be a quicker easier way to do this using MySQL/PHP?

If can you provide position order after pressing each up or down you can use following query. That is if current position is 4,5,73,89, suppose user selected 89 and pressed up. In that case if you can provide 4,5,89,73 to query then following query will help you
select * from table22 order by field(position,4,5,89,73);

you just need to use a simple case in your update statement, see example below for moving a number up. For moving a numberdown, same case with minor adjustment, and you can use a nested case to decide which to use by comparing number and destination
set #nr=4; set #dest=2;
select *,
case
when number between #dest and #nr-1 then number+1
when number=#nr then #dest
else number
end as number_alt
from
(
select 1 as number union select 2 union select 3 union select 4 union select 5
)a

For those that find this page in the future, I found some code from an old shop that did the trick:
if((isset($_POST['moveup_x'])) || (isset($_POST['movedown_x']))) {
$current = select("SELECT `position` FROM `events` WHERE `id`='".rEsc($eventid)."';", true,true);
if(isset($_POST['moveup_x'])) $target = ($current - 1);
if(isset($_POST['movedown_x'])) $target = ($current + 1);
if($current > 1) {
$counter = 1;
foreach(select("SELECT `id` FROM `events` ORDER BY `position`;") as $val)
{
$newposition = $counter;
if($current == $newposition) {
$newposition = $target;
} elseif(($current > $newposition) && ($target <= $newposition)) {
$newposition++;
} elseif(($current < $newposition) && ($target >= $newposition)) {
$newposition--;
}
runSQL("UPDATE `events` SET `position`='{$newposition}' WHERE `id`='{$val['id']}';");
$counter++;
}
array_push($msgs,"Successfully moved event.");
} else {
array_push($msgs,"!Cannot move the event any higher up the list.");
}
}
You need to know your current, which you can get from $_POST (in this case I got from rowID in the database) and your target (I had img submit buttons so I just minused or plussed from whichever button the user clicks). Once you have that, loop through each row in the table however you see fit, (set a counter beforehand) and run the IF/ELSE statement. Modify for your need.
It works very well though. There problably is a quicker/easier way, i.e. all in one SQL statement, instead of updating every single row in the database, but I couldnt find it.

Related

Trying to show only the last 4 results of a table

I'm new to PHP...
We have a table that get lots of rows with data and we need to show only the last 4 rows of it.
This is the code before the table:
while ($counter < $i) { // strat while loop, echo guests
if ($counter == 4) { break; }
right now it displays the first 4 rows
Note that we don't want to use SQL LIMIT 4 because the data can be changed from the user actions that we asks before the while.
Try to use SQL ORDER BY id DESC - this will select your collection in reverce order. (or it could be other column instead id which you are using as primary key)

Creating a next and previous buttons

I'm trying to do a next and previous button based on records from database but i'm not really sure how to do it and which would be the best way.
The way that i was thinking to do it
would be to have a field in the table named position.
and the query would look like this:
SELECT * FROM t1 WHERE step = 1
then in the php i would have something like this
$step = $step + 1 // for the next button
if($step === 1) {
$step = 1;
} else {
$step = $step - 1;
}
But if i would delete a record then my position would be out of sync with the math and i won't be able to do + or - on step field because i would find the record.
Which means everytime i would delete something i would need to do a new increment on that field to keep it synced which might later become a problem.
How should i handle it ?
You can add a row number to a query like this:
select #qposn:=#qposn+1 posn, a.* from sometable a, (select #qposn:=0) x
You can select a specific row, in this case the 2nd row, like this:
select * from (
select #qposn:=#qposn+1 posn, a.* from sometable a, (select #qposn:=0) x
) x where posn=2
But be aware that if the data in the table changes the numbering will change also. If someone deletes the first record in the table then the data that used to be row 2 will now be row 1 and so paging may skip or repeat rows.
If your table is relatively small you might consider caching the table in a javascript array and then paging through the array.

need help to find a php structure solution

I am just a student at php, I am trying to find out a list of members from a table where I dont know how much rows are in that table, but I need every 6 rows on Order By entrytime DESC basis.
My table structure is as below:
int `ID`
int `entrytime` // this time updates when rows insert
now I need to find out all ids on basis of entrytime DESC and insert those ids in a separate new table say "new_tbl" as a group of 6 ids
ind `ID`
varchar `group_name`
I am trying to do like this :
$qry=mysql_query("SELECT id FROM main_table entrytime ASC");
while($res=mysql_fetch_row($qry)){
$id=$res['0'];
$q=mysql_query();
######### But not getting any Idea how to find every 6 Ids and insert in new_tbl #######
}
In your case you use mysql_fetch_row this gives you the count of rows and not the data.
while($res=mysql_fetch_assoc($qry)) {
To get the Data you have to use mysql_fetch_assoc for example.
To find every 6 Ids you can make a counter and increment the value by 1. If the modulo of 6 and the value is 0 you have the sixth value and you can reset the counter.
$i = 1;
while ...
if($i % 6 == 0) {
// reset your counter
$i = 1;
}
$i++;
}
Then you can use the counter to work with it and write that to another table for example.

PHP/MySQL make top 10 out of selection

A user can input it's preferences to find other users.
Now based on that input, I'd like to get the top 10 best matches to the preferences.
What I thought is:
1) Create a select statement that resolves users preferences
if ($stmt = $mysqli->prepare("SELECT sex FROM ledenvoorkeuren WHERE userid = you"))
$stmt->bind_result($ownsex);
2) Create a select statement that checks all users except for yourself
if ($stmt = $mysqli->prepare("SELECT sex FROM ledenvoorkeuren WHERE userid <> you"))
$stmt->bind_result($othersex);
3) Match select statement 1 with select statement 2
while ($stmt->fetch()) {
$match = 0;
if ($ownsex == $othersex) {
$match = $match + 10;
}
// check next preference
4) Start with a variable with value 0, if preference matches -> variable + 10%
Problem is, I can do this for all members, but how can I then select the top 10???
I think I need to do this in the SQL statement, but I have no idea how...
Ofcourse this is one just one preference and a super simple version of my code, but you'll get the idea. There are like 15 preference settings.
// EDIT //
I would also like to see how much the match rating is on screen!
Well, it was a good question from the start so I upvoted it and then wasted about 1 hour to produce the following :)
Data
I have used a DB named test and table named t for our experiment here.
Below you can find a screenshot showing this table's structure (3 int columns, 1 char(1) column) and complete data
As you can see, everything is rather simple - we have a 4 columns, with id serving as primary key, and a few records (rows).
What we want to achieve
We want to be able to select a limited set of rows from this table based upon some complex criteria, involving comparison of several column's values against needed parameters.
Solution
I've decided to create a function for this. SQL statement follows:
use test;
drop function if exists calcMatch;
delimiter //
create function calcMatch (recordId int, neededQty int, neededSex char(1)) returns int
begin
declare selectedQty int;
declare selectedSex char(1);
declare matchValue int;
set matchValue = 0;
select qty, sex into selectedQty, selectedSex from t where id = recordId;
if selectedQty = neededQty then
set matchValue = matchValue + 10;
end if;
if selectedSex = neededSex then
set matchValue = matchValue + 10;
end if;
return matchValue;
end//
delimiter ;
Minor explanation
Function calculates how well one particular record matches the specified set of parameters, returning an int value as a result. The bigger the value - the better the match.
Function accepts 3 parameters:
recordId - id of the record for which we need to calculate the result(match value)
neededQty - needed quantity. if the record's qty matches it, the result will be increased
neededSex - needed sex value, if the record's sex matches it, the result will be increased
Function selects via id specified record from the table, initializes the resulting match value with 0, then makes a comparison of each required columns against needed value. In case of successful comparison the return value is increased by 10.
Live test
So, hopefully this solves your problem. Feel free to use this for your own project, add needed parameters to function and compare them against needed columns in your table.
Cheers!
Use the limit and offset in query:
SELECT sex FROM ledenvoorkeuren WHERE userid = you limit 10 offset 0
This will give the 10 users data of top most.
You can set a limit in your query like this:
SELECT sex FROM ledenvoorkeuren WHERE userid <> yourid AND sex <> yourpreferredsex limit 0, 10
Where the '0' is the offset, and the '10' your limit
More info here
you may try this
SELECT sex FROM ledenvoorkeuren WHERE userid = you limit 0, 10 order by YOUR_PREFERENCE

How to select every nth row in mySQL starting at n

I have created a question Here That I think is a little bloated. To skim down this question here is my requirements:
I need to create 3 mySQL queries that grab all information in that row so that I can format the information into one of HTML tables.
Here is the query that I have which selects everything:
$qry_questions = mysql_query("SELECT * FROM mbr_qa_questions ORDER BY q_votes DESC);
while($row = mysql_fetch_array($qry_questions){
//Grab all information
}
Now, I need to make three queries that act like the one above, but I need it to do something like this:
pull everything from every third row in a table starting at row #1
pull everything from every third row in a table starting at row #2
pull everything from every third row in a table starting at row #3
Then I would put each of those queries into one of the 3 columns.
I can not do this by unique ID. Yes, it is an auto incrementing ID, but it will be probable that I might have to move whole rows into another table.
EDIT: I've added my attempt to count each row and place the queried result into the right "bin"
//GIVE EACH ENTRY A COLUMN NUMBER
$count++;
if($count >= 4){
$count = 1;
}?>
<div class="col" id="col-1">
<?PHP
while($count == 1){
include("pieces/answers/newAnswerLayout.php");
}
?>
</div>
<div class="col" id="col-2">
<?PHP
while($count == 2){
include("pieces/answers/newAnswerLayout.php");
}
?>
</div>
<div class="col" id="col-3">
<?PHP
while($count == 3){
include("pieces/answers/newAnswerLayout.php");
}
?>
</div>
Here's one approach, to get the resultset returned by MySQL. (But it might be easier to just return all the rows, and get every third row within the app). But it can be done in MySQL pretty easily. Note that your original query is wrapped in parens (as an inline view) aliased as r.
SELECT r.*
FROM (
SELECT *
FROM mbr_qa_questions
ORDER BY q_votes DESC
) r
CROSS
JOIN ( SELECT #i := 0 ) s
HAVING ( #i := #i + 1) MOD 3 = 1
That will return every third row, starting with the first row. To get every third row starting with the 2nd and 3rd row, replace the literal = 1 in the HAVING clause with = 2 or = 3 (respectively).
Why do you need three different queries? Can you not, instead, keep the single query you have, have a counter that is incremented in every iteration of the loop, and on %3 does whatever you would do for cases #1, #2 or #3?
you can probably just use a counter to do it in a much simpler fashion, but I would do it like this:
$questions = array();
$results = mysql_query("SELECT * FROM mbr_qa_questions ORDER BY q_votes DESC");
while($row = mysql_fetch_array($results)){
$questions[] = $row;
}
for($i = 0; $i < count($questions); $i++) {
if($i + 1 % 3 == 0) {
$questions[$i];//this is a 3rd, so do something with it
}
}

Categories