mysql - update date field if exist - php

I have query that save the reservation number that user watch. the system always display the last 10 reservation per user (sort by "createDate" column), so if some reservation number is already in the last 10 the query don't do anything.
I would like to change it a little bit and if the reservation number is already in the table than to update the field "createDate" with the current date and time.
If not exist than insert new row.
What should i change?
$query = "
INSERT INTO user_last_view
(userID,
page,
refid,
mode)
SELECT ".$_SESSION['userDetails']['userID'].",
'".$page."',
".$refID.",
'".$mode."'
FROM dual
WHERE NOT EXISTS (SELECT *
FROM (SELECT ulv.userID,
ulv.page,
ulv.refid
FROM user_last_view ulv
ORDER BY ulv.createdate
DESC LIMIT 10) x
WHERE x.userID = ".$_SESSION['userDetails']['userID']."
AND x.page = '".$page."'
AND x.refid = ".$refID.");
";
$conn->query($query);

Related

how to return records with dates in array less than a particular date

To simplify, each record in a database has Company Name, the Total Spend and Nights reserved. The Nights reserved are stored in the form of a string and then parsed later in the process.
example: Customer= "Bob's Heating" Total= 3000 Reserved= "1/2/2017,1/3/2017,1/5/2017..."
I need to write a query that selects all record whose reservations begin on or before a particular date, so if the target date was "1/4/2017" Bob Heating's record above would be returned.
Any help would be appreciated,
Jim
1.) Create a new table in your database called "reservation_dates" that has the columns: row_id (INT), the_date (DATE)
2.) Run a script in PHP that moves all of those dates into another table that stores them as DATE data types.
Example PHP script:
$statement = "SELECT * FROM my_table";
$result = mysqli_query($con, $statement) or die(mysqli_error($con));
while ($row = mysqli_fetch_assoc($result))
{
$dates = explode(",", $row['Reserved']);
foreach($dates as $date)
{
mysqli_query($con, "INSERT INTO reservation_dates (row_id, the_date) VALUES ('".$row['id']."', '$date')") or die(mysqli_error($con));
}
}
Run the PHP script. Now you will have all of your dates in a relational table called reservation_dates.
Next, to select all of the rows that fall within 1/4/2017, run a query such as
SELECT customer.* FROM reservation_dates reservation JOIN my_table customer ON customer.id = reservation.row_id WHERE MAX(reservation.the_date) >= '2017-04-01' AND MIN(reservation.the_date) <= '2017-04-01' GROUP BY row_id
I typed this quickly without actually trying the code but that's the general approach I would take. Hope it helps!
select *
from dbo.March2010 A
where A.Date <= Convert(datetime, '2010-04-01' )

Add MySQL Count Column to PHP/HTML Table

I'm developing a website using HTML, PHP and MySQL to access a database. On one page I present a table with data from that database. This is some of the code I'm using:
$sql1 = "SELECT * FROM MyTable ORDER BY ID ASC";
$rs1 = mysqli_query($link,$sql1);
(...)
while($row1 = mysqli_fetch_assoc($rs1)) {
echo "<tr><td>".$row1['ID']."</td><td>".$row1['Field1']."</td><td></td><td>".$row1['Field2']."</td><td>".$row1['Field3']."</td></tr>\n" ;
}
Notice the empty <td></td>? That's because I want to have there the number of time a given ID appears on two other tables (there are foreign keys involved, obviously). I have sorted out the code I need for that:
$sql2 = "SELECT (SELECT COUNT(*) FROM MyTable2 WHERE ID2=$row1['ID'])+(SELECT COUNT(*) FROM MyTable3 WHERE ID2=$row1['ID']) AS total";
However, I'm struggling with figuring out a way to add this result to the other table. Any help?
try with this.. it inserts the total to an table after selecting the count.
"INSERT INTO total_table (total)
SELECT (SELECT COUNT(*) FROM MyTable2 WHERE ID2=$row1['ID'])+(SELECT COUNT(*) FROM MyTable3 WHERE ID2=$row1['ID']) AS total
WHERE cid = 2"

how to get rows that repeated X times or more?

I have a table that contains some data. i have a 'username' field in my table that stores users username.
in this table there is possible that a user have many records.
now, how can i get the users that their username repeated more than X times? (50 time or more for example?)
and after that i want to delete rows for each user that i get in previous step but i need to keep first X rows and i need to delete all rows after row X for each user.
how can i do this with mysql and php?
update: i solve my problem with this:
SELECT username, count(*) as numRecords
FROM table
GROUP BY username
This will take a number of steps to achive..
Start by building a query to count the number of records for each user
SELECT username, count(*) as numRecords
FROM table
GROUP BY username
Then add:
HAVING numRecords > 5
to narrow down to usernames with more than 5 records..
Loop through the records from the query above..
foreach($results as $result){
// Query db using `username` to get the 'record to keep'
"SELECT * FROM table
WHERE username = $result['username']
ORDER BY someUniqueID
LIMIT 1"
__Execute the query__
__Store the record ID to keep__
// Delete records (except the one to keep)
"DELETE FROM table
WHERE username = $result['username']
AND someUniqueID != $someUniqueID"
__Execute the query__
}
SELECT DISTINCT `username`, COUNT(`username`) AS `numRecords`
FROM `table`
GROUP BY `username`
HAVING `numRecords` > 'someNumber'

fetching record according current date

can any one explain how i would display my table record according date, like any user of my website can see their activity of current date only...
while($data=mysql_fetch_array($rs))
{
$data["create_date"]=date("M d,y" , $data[create_date]);
i am using this but it displaying previous date result also
here is my code, i am fetching result from different tables
$SQL="select * from $tab where 1 $con ORDER BY id desc $_REQUEST[sort_mode] $con_limit";
while($data=mysql_fetch_array($rs))
{
$data["create_date"]=date("M d,y" , $data[create_date]);
gri("users","WHERE id='$data[op_id]' ","",$op_name);
gri("patient", " where id ='$data[patient_id]' order by id desc","",$patient);
$data[first_name]=$patient[first_name];
$data[last_name]=$patient[last_name];
$data[age]=$patient[age];$data[sex]=$patient[sex];
$data[mob]=$patient[mob];
$data[op_name]=$op_name[name];
$t->set_var($data);
$t->set_var(array("chk_status_$data[id]_$data[status]"=>"selected",));
$t->parse("ABlockList","AccessBlockList",true);
}
You can also use MySQL for this.
Example
select * from table_name where create_date >= NOW();
OR
SELECT * FROM table_name WHERE DATE(create_date) = CURDATE();
OR
SELECT * FROM table_name WHERE DATE(create_date) = DATE(NOW())
DATE() returns the date without time and NOW() returns the current date & time (note we’ve used the DATE() function in this query to remove the time)

high score database

This is a high level/design type question rather than anything specific.
In this game http://koreanwordgame.com/ users have to get as many correct answers as possible in a minute (though its set to 5 seconds for development purposes). As soon as the minute is up I fire an Ajax call with JQuery passing the users score.
On the server side I use this SQL query to get the 5 scores above and 5 below
$getquery = "(SELECT *
FROM highscore
WHERE score >= '$score'
ORDER BY score ASC
LIMIT 5)
UNION ALL
(SELECT *
FROM highscore
WHERE score < '$score'
ORDER BY score DESC
LIMIT 5)";
This returns an HTML table to the client which you will see upon completing the (5 sec) challenge (you don't have to get any answers right).
Now, ultimately I want the table to be about 100 rows long (although it will still only display the surrounding 10 cells, 5 above, 5 below), with the rows position (ID) determined not chronological as it is now but by the score, so that if someone gets 1000 answers right they would go straight into position 1 on the database. Obviously if a user gets lower than any of the 100 rows already existing in the table then it should simply be discarded. Then when the table comes back I want a text input to appear inside the table cell where the user is placed so they can enter their name and fire off another Ajax call so their entry gets inserted into the right place in the database.
I know it would be easier just to ask the user to enter their details first and then scoop off the top 10 results whether they got there or not, but the idea is that I want anyone to be able to get some kind of entry as this will encourage people to play more.
A tough one perhaps..I certainly haven't been able to find anything similar by Googling, all help much appreciated!
EDIT:
In case anyone is interested this is what I ended up with, it's far from finished I need to make it way more robust for example entering an anonymous username in case the user closes the browser and also prevent double posts (though this will be client side).
but thank you everyone for the help, I would not have done it without you. If you see any obvious improvements that could be made feel free to point them out!
<?php
$dbcon = mysql_connect("localhost", "XXXX", "XXXX") or die(mysql_error());
mysql_select_db("tulesblo_koreangame", $dbcon) or die(mysql_error());
mysql_query("SET NAMES utf8");
$name = $_POST["name"];
$email = $_POST["email"];
$score = $_POST["score"];
$table = "";
$submit = "";
$input = "";
$newposition = $_POST['position'];
$position = mysql_query("(SELECT position
FROM highscore
WHERE score < '$score'
ORDER BY score DESC
LIMIT 1)");
if(!$name){
$gethigherrows = "(SELECT *
FROM highscore
WHERE score >= '$score'
ORDER BY score ASC
LIMIT 5)";
$getlowerrows = "(SELECT *
FROM highscore
WHERE score < '$score'
ORDER BY score DESC
LIMIT 5)";
$higherrows= mysql_query($gethigherrows);
$lowerrows= mysql_query($getlowerrows);
if(mysql_error())echo mysql_error();
while($row=mysql_fetch_array($higherrows))
{
$uppertable .= "<tr><td>$row[position]</td><td>$row[name]</td> <td>$row[score]</td></tr>";
}
$x = 0;
if (mysql_num_rows($lowerrows) > 0)
{ mysql_query("UPDATE highscore SET position = position + 1 WHERE score < '$score'")or die("update failed");
while($row=mysql_fetch_array($lowerrows))
{
if ($x == 0)
{$position = $row['position'];};
$x++;
$newpos = $row[position]+1;
$lowertable.= "<tr><td>$newpos</td><td>$row[name]</td> <td>$row[score]</td></tr>";
}
$input = "<tr><td id='position'>$position</td><td><input id='nameinput'type='text' /></td><td>$score</td></tr>";
$submit = "<br />Enter email if you want to receive a prize!<br /><input id='emailinput'type='text' /><br /><input id='submithighscore'type='submit' value='Submit'>";
}
$table .= "<table id='scoretable'><tr><th>Position</th><th>Name</th><th>Score</th></tr>";
$table .= $uppertable;
$table .= $input;
$table .= $lowertable;
$table .= "</table>";
$table .= $submit;
$table .= "<br /><span class='msg'></span>";
echo $table;
}else{ echo($newposition);
mysql_query("INSERT INTO highscore VALUES (NULL, '$score', '$name', '$email', '$newposition')");
}
?>
You did not say where lies your problem, but I suppose it's mostly a misconception about SQL. Here's how I would do the whole app.
For the SQL schema:
You shouldn't care about the order of the rows in the DB. You can set the order in the queries (SELECT, etc). There is no "right place" to insert.
You don't need a "rank" column, for the same reason.
Your table can be as simple as: id (INT AUTO_INCREMENT), name, score, when (timestamp).
Initialize it with 100 dummy scores.
For the workflow:
Do not care for performance now, aim for readability.
As you wrote, once a player has finished, use AJAX to find the 10 surrounding scores. You already have the SQL queries for this part. You can either prepare the HTML on the server side in PHP, or send raw data in order build the HTML with Javascript. This can be done in one request (use json_encode() in PHP to return an array/object).
If there are no scores below, then it's not one of the 100 best scores, do nothing.
Else, ask the user its name, and send a new AJAX request. The SQL can be kept simple:
INSERT INTO Highscore SET name=?, score=?, when=NOW()
After each insertion, delete the lowest score
DELETE FROM Highscore ORDER BY score ASC, when DESC LIMIT 1
If you want to prevent cheating, you'll need to add hashes in your ajax calls. For instance, send (username, score, hash=md5(username.score."secretphrase") and check the hash still matches the username and score.
If you want to display the ranks along with the scores, then put a "rank" colum in your table. When you insert a score, set its rank to the max rank of the lower scores (you already computed this for the first AJAX request, so send it in the second AJAX request). Then UPDATE Highscore SET rank = rank + 1 WHERE score < ?.
I'm havinga pickle to understand what you're exactly after. Here's a query to insert the result in the highscore.
$str_user_id = $_GET['user_id'];
$str_score = $_GET['score'];
mysql_query("
INSERT INTO highscore (position, user_id, score)
SELECT (#rownum := $rownum + 1) AS position, user_id, score
FROM (SELECT user_id, score
FROM (SELECT '{$str_user_id}' AS user_id, '{$str_score}' AS score
UNION ALL
SELECT user_id, score
FROM highscore) AS h, (#rownum := 0) AS vars
WHERE '{$str_score}' <= 100
ORDER BY score ASC) AS h2)
LIMIT 100
ON DUPLICATE KEY UPDATE user_id = VALUES(user_id), score = VALUES(score)
");
I couldn't entirely make sense of your question, but based on this:
"I know it would be easier just to ask the user to enter their details first and then scoop off the top 10 results whether they got there or not, but the idea is that I want anyone to be able to get some kind of entry as this will encourage people to play more"
I suspect you want the score table shown to the user to look something like this:
1. John Doe (score: 1,000,000)
2. Larry Roe (score: 999,999)
3. Jane Doe (score: 985,742)
...
5746. Susan Player (score: 894)
5747. *** YOU *** (score: 893)
5748. Joe R. Player (score: 889)
I second Mytskine's initial suggestion that you shouldn't try to store the ranks in the DB at all — keeping a rank column up to date is possible, like Mytskine shows at the end of their answer, but it's a lot of work for little if any gain. Just have your score table consist of the obvious columns like name and score and time, plus maybe an AUTO_INCREMENT column id.
Now, let's say you want to show the N highest-scoring players, plus K players before and after the new score. First, we need to figure out the player's rank:
SELECT COUNT(*) + 1 FROM scores WHERE score > ?
Here, the ? is a placeholder for the player's score. This counts how many players have a higher score than the one we're going to insert below. If we favor the latest scores in the case of ties, this plus one will be the player's rank. Let's denote this rank by R.
Now, if R < N + K, we might was well just show the top N + 2*K (or max(N, R+K) or whatever) entries:
SELECT * FROM scores ORDER BY score DESC, time DESC LIMIT N+2*K
Otherwise, we need to do it in three steps: first, fetch the top N entries:
SELECT * FROM scores ORDER BY score DESC, time DESC LIMIT N
then, the K entries above the player:
SELECT * FROM scores WHERE score > ? ORDER BY score ASC, time ASC LIMIT K
and finally the K entries below the player:
SELECT * FROM scores WHERE score <= ? ORDER BY score DESC, time DESC LIMIT K
Note that the second result set will be in reverse order, but that's OK — just reverse it in PHP. Now we need to assign ranks to the entries we've fetched, but that's simple: the first set has ranks 1 to N, the second set (after reversal) has ranks R-K to R-1, and the last set has ranks R+1 to R+K. (Rank R belongs to the current player, of course.)
Finally, after the player has entered their name, we can insert the player's score into to the database simply with:
INSERT INTO scores (name, score, time) VALUES (?, ?, ?)
If you want, you can also remove the lowest scores from the database at this point to limit its size, but in practice it probably won't matter unless you have literally billions of players. (A single score entry is going to take a few dozen bytes, mostly depending on how long a name the player enters, so a million entries will still be just a few dozen megabytes.) You should, however, remember to create an index on (score, time) to keep the queries efficient.

Categories