Reputation: 7351
I have two tables described below. What I need is a single query that will tell me the players whose score hasn't changed in a given number of days.
CREATE TABLE players (
pid INT(50),
name VARCHAR(255),
updatedAt DATETIME
);
CREATE TABLE pl_scores (
pid INT(50),
score INT(255),
updatedAt DATETIME
);
The players
table keeps a master list of all players along with other non-changing data not shown here for the sake of brevity. The pl_scores
table keeps a running history of score changes in order to track growth and other values that might change. A new record is inserted into pl_scores
for each player every 6 hours.
What I would like to get is the pid
of the players that haven't had a change of score in a certain number of days, but I am unsure of how to group that in order to get the correct values.
Example dataset
(only shows last score of each day which is only one needing to be compared really)
+------+------+-------+------+---------+---------------------+
| pid | aid | score | rank | cityCnt | updatedAt |
+------+------+-------+------+---------+---------------------+
| 1660 | 0 | 801 | 2111 | 1 | 2012-06-20 22:14:11 |
| 1660 | 0 | 801 | 2250 | 1 | 2012-06-21 22:15:45 |
| 1660 | 0 | 801 | 2387 | 1 | 2012-06-22 22:17:06 |
| 1660 | 0 | 801 | 2547 | 1 | 2012-06-23 22:17:09 |
| 1660 | 0 | 801 | 2702 | 1 | 2012-06-24 22:19:50 |
| 1660 | 0 | 801 | 2836 | 1 | 2012-06-25 22:21:07 |
| 1660 | 0 | 801 | 2956 | 1 | 2012-06-26 21:42:44 |
+------+------+-------+------+---------+---------------------+
EDIT
The answer found below worked perfectly, but now I'd like to take it a step further and limit the results by a hardcoded value found in a 3rd table. Here is the working SQL statement
SELECT a.pid, c.aid, b.name AS pName, c.name AS aName, a.score FROM pl_scores AS a
JOIN players AS b ON a.pid = b.pid
JOIN alliances AS c ON b.aid = c.aid
WHERE a.updatedAt >= CURRENT_DATE() - INTERVAL 3 DAY GROUP BY a.pid HAVING MIN(a.score) = MAX(a.score);
Each player has multiple cities throughout the world. I'd like to limit the results by players with cities found on a given continent. For example, I want to find every player that hasn't changed their score in the last 3 days on continent 34
. The cities
table looks like this:
CREATE TABLE cities (
cid INT(50),
pid INT(50),
name VARCHAR(255),
cont INT(10),
updatedAt DATETIME
);
Upvotes: 2
Views: 275
Reputation: 11
SELECT a.pid, c.aid, b.name AS pName, c.name AS aName, a.score FROM pl_scores AS a
JOIN players AS b ON a.pid = b.pid
JOIN alliances AS c ON b.aid = c.aid
JOIN cities AS d ON a.pid = d.pid
WHERE
a.updatedAt >= CURRENT_DATE() - INTERVAL 3 DAY
AND d.cont = 34
GROUP BY a.pid HAVING MIN(a.score) = MAX(a.score);
Upvotes: 1
Reputation: 77687
You could get pid
s of players with their scores unchanged like this:
SELECT pid
FROM pl_scores
WHERE updatedAt >= CURRENT_DATE() - INTERVAL n DAY
GROUP BY pid
HAVING MIN(score) = MAX(score)
Now you can use those pid
s to get full (or just more) information about the corresponding players, i.e. like this:
SELECT * /* or you could specify the necessary columns here */
FROM players
WHERE pid IN (
SELECT pid
FROM pl_scores
WHERE updatedAt >= CURRENT_DATE() - INTERVAL n DAY
GROUP BY pid
HAVING MIN(score) = MAX(score)
)
Upvotes: 1
Reputation: 3763
Assuming your updatedAt
contains when an entry was made and not the update time, using 3 days as the time to check:
SELECT pid FROM
(SELECT * FROM pl_score GROUP BY pid HAVING updatedAt > DATE_SUB(NOW(), INTERVAL 3 DAY) AND COUNT(DISTINCT(score)) = 1) AS y
JOIN pl_score ON y.pid = pl_score.pid;
Read this page to learn more about this sort of problem.
I can't guarantee that this'll work, but give it a try.
Upvotes: -1
Reputation: 106375
I suppose it can be done with something like this:
SELECT plf.pid,
COALESCE(plf.score, 0) AS former_score,
COALESCE(pll.score, 0) AS latter_score
FROM pl_scores AS plf
RIGHT JOIN (
SELECT pid, score FROM pl_scores
WHERE DATE(updatedAt) = DATE(NOW())
) as pll
ON plf.pid = pll.pid
WHERE DATE(updatedAt) = DATE(DATE_SUB(NOW(), INTERVAL 3 DAY))
HAVING former_score = latter_score
Upvotes: 2
Reputation: 7212
I think something like this will work:
SELECT pid, MIN(updatedAt) AS last FROM pl_scores GROUP BY pid, score HAVING last > '2012-06-24'
Upvotes: 0