用于检测非更改值的高级SQL语句 - MySQL

时间:2012-06-29 03:33:09

标签: mysql sql

我有两个表格如下所述。我需要的是一个单一的查询,它会告诉我在给定天数内得分没有变化的球员。

CREATE TABLE players (
  pid INT(50),
  name VARCHAR(255),
  updatedAt DATETIME
);

CREATE TABLE pl_scores (
  pid INT(50),
  score INT(255),
  updatedAt DATETIME
);

为了简洁起见,players表保留了所有玩家的主列表以及此处未显示的其他非变化数据。 pl_scores表保留了分数变化的运行历史记录,以跟踪可能发生变化的增长和其他值。每6小时为每位玩家添加一条新记录pl_scores

我想得到的是pid在一定天数内没有得分变化的球员,但我不确定如何对其进行分组以获得正确的值。

示例数据集

(仅显示每天的最后得分,这只是一个需要真正比较的得分)

+------+------+-------+------+---------+---------------------+
| 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 |
+------+------+-------+------+---------+---------------------+

修改

下面找到的答案工作得很好,但现在我想更进一步,并通过第3个表中的硬编码值限制结果。这是工作的SQL语句

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);

每个玩家在世界各地都有多个城市。我想限制在特定大陆上找到的城市玩家的结果。例如,我想找到在大陆34过去3天内未改变分数的每位球员。 cities表如下所示:

CREATE TABLE cities (
  cid INT(50),
  pid INT(50),
  name VARCHAR(255),
  cont INT(10),
  updatedAt DATETIME
);

5 个答案:

答案 0 :(得分:2)

我想可以用这样的东西来完成:

      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

答案 1 :(得分:1)

你可以让pid个玩家的得分保持不变:

SELECT pid
FROM pl_scores
WHERE updatedAt >= CURRENT_DATE() - INTERVAL n DAY
GROUP BY pid
HAVING MIN(score) = MAX(score)

现在您可以使用这些pid来获取有关相应玩家的完整(或更多)信息,例如:

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)
)

答案 2 :(得分:1)

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);

答案 3 :(得分:0)

我觉得这样的事情会奏效:

SELECT pid, MIN(updatedAt) AS last FROM pl_scores GROUP BY pid, score HAVING last > '2012-06-24'

答案 4 :(得分:-1)

假设您的updatedAt包含条目的时间而不是更新时间,请使用3天作为检查时间:

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;

阅读this page以了解有关此类问题的更多信息。

我不能保证这会起作用,但试一试。