I wrote a code that lets the user vote for one out of the two options and the score is calculated using a modified Elo rating system. However, digits to the right of the decimal point are ignored when I vote for either of the options. I added the floatval function but it didn't help.
$query = "SELECT pic,score,id FROM nfl
JOIN (SELECT r1.random_id
FROM nfl_map AS r1
JOIN (SELECT (RAND() *
(SELECT MAX(row_id)
FROM nfl_map)) AS row_id)
AS r2
WHERE r1.row_id >= r2.row_id
ORDER BY r1.row_id ASC
LIMIT 1) as rows ON (id = random_id)";
$query_2 = "SELECT pic,score,id FROM nfl
JOIN (SELECT r1.random_id
FROM nfl_map AS r1
JOIN (SELECT (RAND() *
(SELECT MAX(row_id)
FROM nfl_map)) AS row_id)
AS r2
WHERE r1.row_id >= r2.row_id
ORDER BY r1.row_id ASC
LIMIT 1) as rows ON (id = random_id)";
$res_2 = $mysqli->query($query_2);
if (!$res_2) die ("Result display failed: " . $mysqli->errno . " - " . $mysqli->error);
$pic_2 = $res_2->fetch_assoc();
$id_2 = $res_2->fetch_assoc();
$score_2 = $res_2->fetch_assoc();
$res_1 = $mysqli->query($query);
if (!$res_1) die ("Result display failed: " . $mysqli->errno . " - " . $mysqli->error);
$pic_1 = $res_1->fetch_assoc();
$id_1 = $res_1->fetch_assoc();
$score_1 = $res_1->fetch_assoc();
$Ra = $score_1;
$Rb = $score_2;
$calc_pow_1 = (($Rb - $Ra) / 400);
$calc_pow_2 = (($Ra - $Rb) / 400);
$float_calc_pow_1 = floatval($calc_pow_1);
$float_calc_pow_2 = floatval($calc_pow_2);
$Ea = 1 / (1 + pow(10,$float_calc_pow_1));
$Eb = 1 / (1 + pow(10,$float_calc_pow_2));
$float_Ea = floatval($Ea);
$float_Eb = floatval($Eb);
// if user votes for picture no. 1
if (isset($_POST['vote_1']) && isset($_POST['id']) && isset($_POST['score']))
{
$id = $_POST['id'];
/* $score = $_POST['score'];
$pic = $_POST['pic']; */
//$mod = 2 * $Eb;
$K = 4;
$float_mod_1 = floatval($K * (1 - $float_Ea));
$query = "UPDATE nfl SET score=?+$float_mod_1 WHERE id=?";
// $score_new = $_POST['score'] + $mod;
$score_new = $_POST['score'] + $float_mod_1;
$stmt = $mysqli->prepare($query);
$stmt->bind_param('di', $_POST['score'], $_POST['id']);
$stmt->execute();
if ($stmt->errno) {
echo "Vote failed: " . $stmt->error();
}
else echo "Vote succeeded! New score of $id_1 is $score_new!";
$stmt->close();
}
// fetch picture no. 2
//
// query to the database
/* $query_2 = "SELECT pic,score,id FROM nfl
JOIN (SELECT r1.random_id
FROM nfl_map AS r1
JOIN (SELECT (RAND() *
(SELECT MAX(row_id)
FROM nfl_map)) AS row_id)
AS r2
WHERE r1.row_id >= r2.row_id
ORDER BY r1.row_id ASC
LIMIT 1) as rows ON (id = random_id)";
$res_2 = $mysqli->query($query_2);
if (!$res_2) die ("Result display failed: " . $mysqli->errno . " - " . $mysqli->error);
$pic_2 = $res_2->fetch_assoc();
$id_2 = $res_2->fetch_assoc();
$score_2 = $res_2->fetch_assoc(); */
// if user votes for picture no. 2
if (isset($_POST['vote_2']) && isset($_POST['id']) && isset($_POST['score']))
{
$id = $_POST['id'];
/* $score = $_POST['score'];
$pic = $_POST['pic']; */
//$mod = 2 * $Ea;
$K = 4;
$float_mod_2 = floatval($K * (1 - $float_Eb));
$query = "UPDATE nfl SET score=?+$float_mod_2 WHERE id=?";
// $score_new = $_POST['score'] + $mod;
$score_new = $_POST['score'] + $float_mod_2;
/* $query = "UPDATE nfl SET score=?+1 WHERE id=?";
$score_new = $_POST['score'] + $mod; */
$stmt = $mysqli->prepare($query);
$stmt->bind_param('di', $_POST['score'], $_POST['id']);
$stmt->execute();
if ($stmt->errno) {
echo "Vote failed: " . $stmt->error();
}
else echo "Vote succeeded! New score of $id_2 is $score_new!";
$stmt->close();
}
Here is the full code, if you need to see it: http://snipt.org/vDhj2
The code handling the situation when the user votes for the second option is pretty much the same (except $Ea changes to $Eb etc.). The 'score' row's properties in MySQL are following:
float(8,3) not null
Thanks.
EDIT: I'm not getting the notice anymore.
I think you simply missed a declaration in your code:
$res_1 = $mysqli->query($query);
if (!$res_1) die ("Result display failed: " . $mysqli->errno . " - " . $mysqli->error);
$pic_1 = $res_1->fetch_assoc();
$id_1 = $res_1->fetch_assoc();
$score_1 = $res_1->fetch_assoc();
$Ra = $score_1;
$Rb = $score_2;
I cannot see $score_2 defined anywhere in the code above where you try to assign it's value to another variable.
Warnings are there for a reason - ignoring them is a bad idea as it will inevitably lead to an error in your code. in this case, you simply need to declare your variable before you assign it (even if it is si,ply $score_2=0; if that is to be the default value, but assign it nonetheless.
Since it's just a notice, does it matter? If so, what should I change
in my code?
incorrectly written code that throws an error needs to be fixed.
you cannot assign $Rb = $score_2 before you create the $score_2 variable -- that is an error. put them in the right order to solve that problem
Getting a notice in PHP isn't an ERROR obviously, it's just ugly and can burden your load...
the notice you're getting means that you're using a non-set variable, doing a var_dump(isset($score_2)) will result in bool(false), meaning that it wasn't set.
PHP is a dynamically typed language, meaning that you don't have to declare variables prior to using them, however - it's a good practise if you do, to avoid such notices which could result in errors you simply need to declare the variable prior to using it.
are you expecting a number?
initialize it so
$score_2 = 0;
or
$score_2 = null;
depends on your needs, if you fill it with null, don't forget to allow in mysql NULL values...
Okay I found it. It was a stupid mistake with fetch_assoc() etc. Here is the revised code: http://snipt.org/vEaj7
Related
I have the following code
$sql = "SET #uid := (SELECT ID FROM channels WHERE Used = 0 ORDER BY RAND() LIMIT 1);";
$sql = "UPDATE channels SET Used = 1 WHERE ID = #uid;";
$sql = "SELECT * FROM channels WHERE ID IN = #uid;";
$result = mysqli_multi_query($conn, $sql)
or die( mysqli_error($sql) );
if (mysqli_num_rows($result) > 0) {
$text = '';
while($row = mysqli_fetch_assoc($result)) {
$Channel_Location = $row['Channel_Location'];
$text = $text . $Channel_Location;
}
}
Now the issue i'm having is the php isnt displaying the result returned by the MYSQL query which is stored in a session later on in the code to be displayed on a dummy page it comes up with the following error
Warning: mysqli_num_rows() expects parameter 1 to be mysqli_result
The my SQL query does exactly what I need it to I just need to, so I don't really want to change it. I just need some advice on how i'd get the PHP to echo the #uid
is there anyone willing to help me solve the issue? if so thankyou.
You have 3 queries in your $sql so you should use multi_query function
http://php.net/manual/en/mysqli.multi-query.php
And you can change your first query to:
SET #uid = 0;
SELECT #uid := ID FROM channels WHERE Used = 0 ORDER BY RAND() LIMIT 1);
Update You can try this fragment of your code modified with all commented improvements.
$sql = 'SET #uid = 0;';
$sql .= 'SELECT #uid:= ID FROM channels WHERE Used = 0 ORDER BY RAND() LIMIT 1);';
$sql .= 'UPDATE channels SET Used = 1 WHERE ID = #uid;';
$sql .= 'SELECT * FROM channels WHERE ID IN = #uid;';
if (mysqli_multi_query($conn, $sql)) {
do {
$result = mysqli_store_result($conn);
} while(mysqli_next_result($conn));
if (mysqli_num_rows($result) > 0) {
$text = '';
while($row = mysqli_fetch_assoc($result)) {
$Channel_Location = $row['Channel_Location'];
$text = $text . $Channel_Location;
}
}
} else {
die( mysqli_error($conn) );
}
I'm working on a project where I have to show the leaderboard of players. But when wrote the below code, It shows the ranks with 2, 4, 6, 8, ... But not the odd numbered ranks. Can anyone tell me "What's wrong in this ?"
$query1_string = "CREATE VIEW Leaderboard AS SELECT Name, Points, PhoneNo
FROM user ORDER BY Points DESC";
$query2_string = "set #rank = 0";
$query3_string = "SELECT #rank := #rank + 1 as Rank, Name, Points
FROM Leaderboard";
$query5_string = "DROP VIEW Leaderboard";
// Doing the queries
$query1 = mysqli_query($con, $query1_string) or die(mysqli_error($con));
$query2 = mysqli_query($con, $query2_string) or die(mysqli_error($con));
$query3 = mysqli_query($con, $query3_string) or die(mysqli_error($con));
// Initializing the count
$count = 0;
//Making an array of strings including Rank, Name and Points of the Top 5 Players
while (($count < 5) && (mysqli_fetch_array($query3, MYSQL_NUM))) {
$row = mysqli_fetch_array($query3, MYSQL_NUM);
$results[$count] = $row[0] . " " . $row[1] . " " . $row[2];
$count++;
}
// Dropping the view.
$end_query = mysqli_query($con, $query5_string) or die(mysqli_error($con));
//Returning the array
$leader = implode("\n", $results);
echo $leader;
You are executing the query3 two times and displying the data retrieved from second execution
while (($count < 5) && (mysqli_fetch_array($query3, MYSQL_NUM))) {
$row = mysqli_fetch_array($query3, MYSQL_NUM);
I've seen a couple variations on this, but mainly they swap the entire row rather than just one value in that row, and not dynamically.
Here's the issue:
I have three rows each with the following cells (id, title, content, display_order, visible).
id is auto_increment. title and content are manually entered and visible is a toggle. display_order is set when each row is created and automatically set as the highest integer and set at the bottom of the stack.
I set it like this so that if any of these records were to be manually deleted, i can reorder the stack automatically (if there are 4 records, and I delete #2, the new order resets as 1,2,3 and not 1,3,4).
Each row has a set of up and down arrow buttons that call move.php with queries of id(id), display_order(pos) and direction(dir).
In the move.php it uses a conditional to determine whether to move the record UP or DOWN depending on what the direction variable is set at.
What PHP code do I need to write to take these three variables (id, pos, dir) and swap the value in the table cell display_order: Here's a visual representation
Initial:
id title pos
-----------------
1 slide1 1
2 slide2 2
3 slide3 3
After I click the UP button for record ID #3:
id title pos
-----------------
1 slide1 1
2 slide2 3
3 slide3 2
MIND YOU the ID and POS will not always be the same integer
USING davidethell's suggestion I have created this:
Here's what I have created, but all I'm getting is the echo $newPos rather that is going back to the admin.php:
require ("connection.php");
$id = $_GET['id'];
$pos = $_GET['pos'];
$dir = $_GET['dir'];
if ($dir == 'up') {
$newPos = $pos-1;
} else {
$newPos = $pos+1;
}
$fromRow = "SELECT * FROM pages WHERE display_order = ".$pos."";
$toRow = "SELECT * FROM pages WHERE display_order = ".$newPos."";
$reord = mysqli_query($conn, "UPDATE pages SET display_order = " . $toRow['display_order'] . " WHERE id = " . $fromRow['id']."; UPDATE pages SET display_order = " . $fromRow['display_order'] . " WHERE id = " . $toRow['id']);
if ($reord){
header("Location: admin.php");
}else{
echo $newPos;
}
The problem I'm running into is that it only echos the $newPos
UPDATED CODE:
require ("connection.php");
$fromArray = array();
$toArray = array();
$id = $_GET['id'];
$pos = $_GET['pos'];
$dir = $_GET['dir'];
if ($dir == 'up') {
$newPos = $pos-1;
} else {
$newPos = $pos+1;
}
$fromRow = mysql_query("SELECT * FROM pages WHERE display_order = ".$pos."");
$toRow = mysql_query("SELECT * FROM pages WHERE display_order = ".$newPos."");
$reord = mysqli_query($conn, "UPDATE pages SET display_order = " . $toRow['display_order'] . " WHERE id = " . $fromRow['id']);
$reord = mysqli_query($conn, "UPDATE pages SET display_order = " . $fromRow['display_order'] . " WHERE id = " . $toRow['id']);
if ($reord){
header("Location: admin.php");
}else{
echo $newPos;
}
Result: echos the $newPos instead of return to admin.php
You could use this query:
UPDATE
yourtable INNER JOIN (
SELECT
MAX(yourtable.pos) pos_prec,
curr.pos pos_curr
FROM
yourtable INNER JOIN
(SELECT pos FROM yourtable WHERE id=3) curr
ON yourtable.pos<curr.pos
GROUP BY
curr.pos) cp ON yourtable.pos IN (cp.pos_prec, cp.pos_curr)
SET
pos = CASE WHEN pos=cp.pos_curr
THEN pos_prec ELSE pos_curr END
It's a little bit complicated, but it will swap the value of the position where ID=3 with the value of the position of the preceding item, even if there are gaps.
Please see fiddle here.
EDIT
If there are no gaps, you could simply use this to move ID#3 UP:
UPDATE
yourtable INNER JOIN (SELECT pos FROM yourtable WHERE id=3) curr
ON yourtable.pos IN (curr.pos, curr.pos-1)
SET
yourtable.pos = CASE WHEN yourtable.pos=curr.pos
THEN curr.pos-1 ELSE curr.pos END;
and just use +1 instead of -1 to move down (both UP and DOWN can be combined in one single query if needed).
PHP Code
And this is using PHP and mysqli, and assuming that the position is given:
<?php
$mysqli = new mysqli("localhost", "username", "password", "test");
$pos = 3;
$dir = 'down';
if ($dir == 'up') { $newPos = $pos-1; } else { $newPos = $pos+1; }
if ($stmt = $mysqli->prepare("
UPDATE
yourtable
SET
pos = CASE WHEN yourtable.pos=?
THEN ?
ELSE ? END
WHERE
pos IN (?, ?)
AND (SELECT * FROM (
SELECT COUNT(*) FROM yourtable WHERE pos IN (?,?)) s )=2;"))
{
$stmt->bind_param("iiiiiii", $pos, $newPos, $pos, $pos, $newPos, $pos, $newPos);
$stmt->execute();
printf("%d Row affected.\n", $stmt->affected_rows);
$stmt->close();
}
$mysqli->close();
?>
(i also added a check, if trying to move UP the first pos, or DOWN the last one it will do nothing).
Assuming a $row object with each row data, just do:
if ($dir == 'up') {
$fromRow = $row2;
$toRow = $row1;
}
else {
$fromRow = $row1;
$toRow = $row2;
}
$sql = "UPDATE mytable SET pos = " . $toRow['pos'] . " WHERE id = " . $fromRow['id'];
// now execute your SQL however you want in your framework
$sql = "UPDATE mytable SET pos = " . $fromRow['pos'] . " WHERE id = " . $toRow['id'];
// now execute your SQL however you want in your framework
Put that in a function or class of some kind to make it reusable.
EDIT:
Based on your edits it looks like you are not fetching enough information in your queries. They should be:
$fromRow = mysql_query("SELECT * FROM pages WHERE display_order = ".$pos."");
$toRow = mysql_query("SELECT * FROM pages WHERE display_order = ".$newPos."");
You were only selecting the id field, but then you were trying to use the display_order field.
i will not write you the PHP code. But i will give you the SQL:
Let's say $delta is either +1 if the slide's position should be raised 1, or -1 if the slide's position should be lowered by 1.
$id is the id of the slide. Ow, and let's assume the table is called slides_table.
You will need 2 queries:
update slides_table set pos = pos + $delta where id = $id;
update slides_table set pos = pos - $delta where pos = (select pos from slides_table where id=$id) and id != $id
This seems to always return 1 for $item_result->num_rows; even though there are 0 rows in the DB. However, if an item exists it updates the row correctly. I'm sure something is wrong with my syntax but I'm having a hard time wrapping my head around this mysqli.
$item_query = "SELECT COUNT(*) FROM `rel` WHERE `cart_id` = '".$cartId."' && `id_item` = '".$item_id."'";
$item_result = $mysqli->query($item_query) or die($mysqli->error.__LINE__);
if($item_result->num_rows==1) {
$item_query2 = "SELECT * FROM `rel` WHERE `cart_id` = '".$cartId."' && `id_item` = '".$item_id."'";
$item_result2 = $mysqli->query($item_query2) or die($mysqli->error.__LINE__);
$getOldItems = $item_result2->fetch_array();
$oldQty = $getOldItems['amount'];
$oldNotes = $getOldItems['notes'];
$newQty = $oldQty + $item_quantity;
$newNotes = $oldNotes . $item_notes;
$update_qty = $mysqli->query("UPDATE rel SET amount = '$newQty', notes = '$newNotes' WHERE `cart_id` = '$cartId' && `id_item` = '$item_id'");
if(!$update_qty){
printf("Errormessage: %s\n", $mysqli->error);
}
header('Location: ./ordernew.php');
} else {
$insert_cart_item = $mysqli->query("INSERT INTO rel (`email`, `cart_id`, `id_item`, `amount`, `notes`) VALUES ('$email', '$cartId', '$item_id', '$item_quantity', '$item_notes')");
if(!$insert_cart_item) {
printf("Errormessage: %s\n", $mysqli->error);
}
header('Location: ./ordernew.php');
}
When you do SELECT COUNT(*) there will always be at least one result. Even if its 0.
You will need to fetch the result of the query to get the correct count.
<?php
$query1 = "CREATE VIEW current_rankings AS SELECT * FROM main_table WHERE date = X";
$query2 = "CREATE VIEW previous_rankings AS SELECT rank FROM main_table WHERE date = date_sub('X', INTERVAL 1 MONTH)";
$query3 = "CREATE VIEW final_output AS SELECT current_rankings.player, current_rankings.rank as current_rank LEFT JOIN previous_rankings.rank as prev_rank
ON (current_rankings.player = previous_rankings.player)";
$query4 = "SELECT *, #rank_change = prev_rank - current_rank as rank_change from final_output";
$result = mysql_query($query4) or die(mysql_error());
while($row = mysql_fetch_array($result)) {
echo $row['player']. $row['current_rank']. $row['prev_rank']. $row['rank_change'];
}
?>
All the queries work independently but am really struggling putting all the pieces together in one single result so I can use it with mysql_fetch_array.
I've tried to create views as well as temporary tables but each time it either says table does not exist or return an empty fetch array loop...logic is there but syntax is messed up I think as it's the 1st time I had to deal with multiple queries I need to merge all together. Looking forward to some support. Many thanks.
Thanks to php.net I've come up with a solution : you have to use (mysqli_multi_query($link, $query)) to run multiple concatenated queries.
/* create sql connection*/
$link = mysqli_connect("server", "user", "password", "database");
$query = "SQL STATEMENTS;"; /* first query : Notice the 2 semicolons at the end ! */
$query .= "SQL STATEMENTS;"; /* Notice the dot before = and the 2 semicolons at the end ! */
$query .= "SQL STATEMENTS;"; /* Notice the dot before = and the 2 semicolons at the end ! */
$query .= "SQL STATEMENTS"; /* last query : Notice the dot before = at the end ! */
/* Execute queries */
if (mysqli_multi_query($link, $query)) {
do {
/* store first result set */
if ($result = mysqli_store_result($link)) {
while ($row = mysqli_fetch_array($result))
/* print your results */
{
echo $row['column1'];
echo $row['column2'];
}
mysqli_free_result($result);
}
} while (mysqli_next_result($link));
}
EDIT - The solution above works if you really want to do one big query but it's also possible to execute as many queries as you wish and execute them separately.
$query1 = "Create temporary table A select c1 from t1";
$result1 = mysqli_query($link, $query1) or die(mysqli_error());
$query2 = "select c1 from A";
$result2 = mysqli_query($link, $query2) or die(mysqli_error());
while($row = mysqli_fetch_array($result2)) {
echo $row['c1'];
}
It seems you are not executing $query1 - $query3. You have just skipped to $query4 which won't work if the others have not been executed first.
Also
$query4 = "SELECT *, #rank_change = prev_rank - current_rank as rank_change from final_output";
should probably be
$query4 = "SELECT *, #rank_change := prev_rank - current_rank as rank_change from final_output";
or else the value of rank_change will just be a boolean, true if #rank_change is equal to (prev_rank - current_rank), false if it is not. But do you need #rank_change at all? Will you use it in a subsequent query? Maybe you can remove it altogether.
Even better, you could just combine all the queries into one like this:
SELECT
curr.player,
curr.rank AS current_rank,
#rank_change := prev.rank - curr.rank AS rank_change
FROM
main_table AS curr
LEFT JOIN main_table AS prev
ON curr.player = prev.player
WHERE
curr.date = X
AND prev.date = date_sub('X', INTERVAL 1 MONTH)
You should concatenate them:
<?php
$query = "CREATE VIEW current_rankings AS SELECT * FROM main_table WHERE date = X";
$query .= " CREATE VIEW previous_rankings AS SELECT rank FROM main_table WHERE date = date_sub('X', INTERVAL 1 MONTH)";
$query .= " CREATE VIEW final_output AS SELECT current_rankings.player, current_rankings.rank as current_rank LEFT JOIN previous_rankings.rank as prev_rank
ON (current_rankings.player = previous_rankings.player)";
$query .= " SELECT *, #rank_change = prev_rank - current_rank as rank_change from final_output";
$result = mysql_query($query) or die(mysql_error());
while($row = mysql_fetch_array($result)) {
echo $row['player']. $row['current_rank']. $row['prev_rank']. $row['rank_change'];
}
?>