Right now I have a PHP script that is fetching the first three results from a MYSQL database using:
SELECT * FROM table Order by DATE DESC LIMIT 3;
After that command I wanted PHP to fetch the next three results, initially I was going to use:
SELECT * FROM table Order by DATE DESC LIMIT 3,3;
However there will be a delay between the two commands which means that it is very possible that a new row will be inserted into the table during the delay. My first thought was to store the DATE value of the last result and then include a WHERE DATE > $stored_date but if entry 3 and 4 have the same date it will skip entry 4 and return results from 5 onward. This could be avoided using the primary key field which is an integer which increments automatically.
I am not sure which the best approach is, but I feel like there should be a more elegant and robust solution to this problem, however I am struggling to think of it.
Example table:
-------------------------------------------
| PrimaryKey | Data | Date |
-------------------------------------------
| 0 | abc | 2014-06-17 11:43:00 |
| 1 | def | 2014-06-17 12:43:00 |
| 2 | ghi | 2014-06-17 13:43:00 |
| 3 | jkl | 2014-06-17 13:56:00 |
| 4 | mno | 2014-06-17 14:23:00 |
| 5 | pqr | 2014-06-17 14:43:00 |
| 6 | stu | 2014-06-17 15:43:00 |
-------------------------------------------
Where Data is the column that I want.
Best will be using primary key and select like
SELECT * FROM table WHERE pk < $stored_pk Order by DATE DESC LIMIT 3;
And if you have automatically generated PK you should use ORDER BY pk it will be faster
Two options I can think of depending on what your script does:
You could either use transactions: performing these queries inside a transaction will give you a consistent view of the data.
Alternatively you could just use:
SELECT * FROM table Order by DATE DESC;
And only fetch the results as you need them.
Related
I have a php file that will update a table in MySQL. It will update all the done flags from 0 to 1 after a job has completed. I need to query the done=0 starting from the lowest primary key (ID). After the job is done, I update the done=1 and move on to the next row. I have the following table :
--------------------
| ID | test | done |
--------------------
| 1 | test1| 0 |
--------------------
| 2 | test2| 1 |
--------------------
| 3 | test3| 0 |
--------------------
| 4 | test4| 0 |
--------------------
| 5 | test5| 1 |
--------------------
When I do the following query SELECT test FROM mytable WHERE done=0 ORDER BY id ASC it gives me all the test that have done flags that are 0, however, I want to start with the first and handle that first, then move on to the next one and so on. So I need a query that will show me just the first row. How can I do this?
Your query is on the right track, since it already is sorting by ascending id. All you need to do is limit it to only returning the first result, if one exists. Just add LIMIT 1 to the end of the query:
SELECT test FROM mytable WHERE done=0 ORDER BY id ASC LIMIT 1
Hello I am facing hard time trying to realized this task. The problem is that I am not sure in which way this have to be proceeded and couldn't find tutorials or information about realizing this type of task.
The question is I have 2 tables and one connecting table between the two of them. With regular query usually what is displayed is the table header which is known value and them then data. In My case I have to display the table horizontally and vertically since the header value is unknown value.
Here is example of the DB
Clients:
+--------+------ +
| ID | client|
+--------+------ +
| 1 | Sony |
| 2 | Dell |
+--------+------ +
Users:
+--------+---------+------------+
| ID | name | department |
+--------+--------+-------------+
| 1 | John | 1|
| 2 | Dave | 2|
| 3 | Michael| 1|
| 4 | Rich | 3|
+--------+--------+-------------+
Time:
+--------+------+---------------------+------------+
| ID | user | clientid | time | date |
+--------+------+---------------------+------------+
| 1 | 1 | 1 | 01:00:00 | 2017-01-02 |
| 2 | 2 | 2 | 02:00:00 | 2017-01-02 |
| 3 | 1 | 2 | 04:00:00 | 2017-02-02 | -> Result Not Selected since date is different
| 4 | 4 | 1 | 02:00:00 | 2017-01-02 |
| 5 | 1 | 1 | 02:00:00 | 2017-01-02 |
+--------+------+---------------------+------------+
Result Table
+------------+--------+-----------+---------+----------+
| Client | John | Michael | Rich | Dave |
+------------+--------+-----------+---------+----------+
| Sony |3:00:00 | 0 | 2:00:00 | 0 |
+------------+--------+-----------+---------+----------+
| Dell | 0 | 0 | 0 | 2:00:00 |
+------------+--------+-----------+---------+----------+
First table Clients Contains information about clients.
Second table Users Contains information about users
Third Table Time contains rows of time for each users dedicated to different clients from the clients table.
So my goal is to make a SQL Query which will show the Result table. In other words it will select sum of hours which every user have completed for certain client. The number of clients and users is unknown. So first thing that have to be done is Select all users, no matter if they have hours completed or not. After that have to select each client and the sum of hours for each client which was realized for individual user.
The problem is I don't know how to approach this situation. Do I have first to make one query slecting all users then foreach them in the table header and then realize second query selecting the hours and foreaching the body conent, or this can be made with single query which will render the whole table.
The filters for select command are:
WHERE MONTH(`date`) = '$month'
AND YEAR(`date`) ='$year'
AND u.department = '$department'
Selecting single row for tume SUM is:
(SELECT SUM( TIME_TO_SEC( `time` ) ) FROM Time tm
WHERE tm.clientid = c.id AND MONTH(`date`) = '$month' AND YEAR(`date`) ='$year'
This is the query to select the times for a user , here by my logic this might be transformed with GROUP BY c.id (client id), and the problem is that it have to contains another WHERE clause which will specify the USER which is unknown. If the users was known value was for example 5, there is no problem to make 5 subsequent for each user WHERE u.id = 1, 2, 3 etc.
So here are the 2 major problems how to display in same query The users header and them select the sum of hours for each client corresponding the user.
Check out the result table hope to make the things clear.
Any suggestion or answer which can come to resolve this situation will be very helpful.
Thank you!
I have a table of around 6000 records with a date column amongst other columns which represent the deadline for a query. I need to compare the date in the column to todays date which I understand is done something like:
SELECT DATEDIFF(DATE_TO_COMPARE, CURDATE());
However, I then have another comlumn I want to set to that date difference. So for each date, I need to compare, insert the difference in the column difference_in_days, iterate to the next date and repeat.
I am also invoking this function whenever a certain page on my site is loaded using AJAX and PHP/PDO
My SQL knowledge isn't that extensive, how can I achieve this.
Table is kinda of like
field 1, field2, field 3, date_to_compare, field 4, field 5, difference_in_days
| | | | 2016-04-20 | | | |
| | | | 2016-04-25 | | | |
| | | | 2016-04-22 | | | |
| | | | 2016-04-27 | | | |
| | | | 2016-04-29 | | | |
Sonds like you want to do an update?
UPDATE table_name
SET difference_in_days = DATEDIFF(date_to_compare, CURDATE());
This will update every record in the table to the diff of the current date.
However, this will require you running the update every day, if you want that column to maintain relevance.
Alternative Approach:
If you're not querying this a lot, you may be better off using a view, which will update real-time every time you query it.
CREATE VIEW diff_view_name AS
SELECT *, DATEDIFF(date_to_compare, CURDATE()) AS difference_in_days
FROM table_name;
Then you could query it using:
SELECT * FROM diff_view_name;
I wanted to create a system to track the progress of a player in a game. Each player can be a member of multiple groups, which all have other requirements. In order to track his progress, the stats of the player will be saved once he joins a group. Every time he reloads his stats, the current ones should be saved inside the database.
All stats of the player are stored in a json-format, which will then be parsed either by PHP or JS. An entry with compare = 0 is set once the player joins a group. An entry with compare = 1 should be created the first time a player clicks on Update Stats and from then on it should only be updated, not newly created.
Now my question is: How to achieve that? When reading through the syntax of INSERT INTO I got the following:
INSERT INTO `groups` (`grp`, `id`, `json`, `compare`) VALUES
($grp, $id, $json, 1) ON DUPLICATE KEY SET `json` = $json
However, since there is no key set, and I don't know if I can set up two/three keys (as there can be multiple groups per user, as well as the compare = 0 entry in the same group), I don't think I can do it this way.
+------+----+---------+---------+
| grp | id | json | compare |
+------+----+---------+---------+
| 1 | 1 | stats | 0 |
| 1 | 1 | stats | 1 |
| 1 | 2 | stats | 0 |
| 1 | 2 | stats | 1 |
| 2 | 2 | stats | 0 |
| 2 | 3 | stats | 0 |
| 2 | 3 | stats | 1 |
| 2 | 4 | stats | 0 |
| 2 | 5 | stats | 0 |
+------+----+---------+---------+
grp is the group of the player. There is no real limit set to the
number of groups a player can be in.
id is the ID of the player.
json contains the stats of the player in a json
format (number of points, etc).
compare is a boolean. 0 stands for entry stats (the number of points a player
already had when he registered) and 1 stands for the current stats - Which will
be compared to the entry stats, in order to get the difference (= the points a
player made since joining the group).
I hope my explanation was understandable and someone can help me out.
You can use insert raplace:
REPLACE INTO groups (`grp`, `id`, `json`, `compare`) VALUES (...);
But you must have primary key in table. Replace into automaticly finds out primary key and if record exists, it update row, but if doesn't, it add new row.
You can create a unique key with multiple columns. This will trigger the 'on duplicate' clause.
ALTER TABLE groups
ADD UNIQUE (grp, id, compare)
I'm displaying a record set using Datatables pulling records from two tables.
Table A
sno | item_id | start_date | end_date | created_on |
===========================================================
10523563 | 2 | 2013-10-24 | 2013-10-27 | 2013-01-22 |
10535677 | 25 | 2013-11-18 | 2013-11-29 | 2013-01-22 |
10587723 | 11 | 2013-05-04 | 2013-05-24 | 2013-01-22 |
10598734 | 5 | 2013-06-14 | 2013-06-22 | 2013-01-22 |
Table B
id | item_name |
=====================================
2 | Timesheet testing |
25 | Vigour |
11 | Fabwash |
5 | Cruise |
Now since the number of records returned is going to turn into a big number in near future, I want the processing to be done serverside. I've successfully managed to achieve that but it came at a cost. I'm running into a problem while dealing with filters.
From the figure above, (1) is the column whose value will be in int (item_id), but using some small modifications inside the while loop of the mysql resource, I'm displaying the corresponding string using Table B.
Now if I use the filter (2), it is working fine since those values come from Table A
The Problem
When I try to filter from the field (3), if I enter a string value such as fab it says no record found. But if I enter an int such as 11 I get a single row which contains Fabwash as the item name.
So while filtering I'm required to use the direct value used in Table A and not its corresponding string value stored in Table B. I hope the point that I'm putting across is understandable because it is hard to explain it in words.
I'm clueless on how to solve the issue.