从表中选择最新的带时间戳的值,该表对于一个列 id 有多个条目,对于每个唯一的列 id 和来自另一个表的数据
Posted
技术标签:
【中文标题】从表中选择最新的带时间戳的值,该表对于一个列 id 有多个条目,对于每个唯一的列 id 和来自另一个表的数据【英文标题】:Select latest timestamped value from table, which has multiple entries for a column id, for each unique column id and data from another table 【发布时间】:2020-09-24 23:31:29 【问题描述】:我需要从一个学校网站的两个表中提取数据。用户标记(tFlag)他们已经研究并准备回答问题的主题。这些选择记录在 userTopics 表中。有 55 个主题 (topicID),网站上的每个主题都有许多可用的问题 (qID)。
UserTopics 表还列出了每个主题的绩效滚动评级,即 topicScore。每个 topicID 的任何用户都只会有一个唯一的行。
用户主题
| ID | userID | topicID | tFlag | topicScore |
| 25 | 1 | 1 | 1 | 25 |
| 29 | 1 | 2 | 1 | 70 |
| 42 | 1 | 3 | 0 | 5 |
| 41 | 1 | 5 | 0 | 5 |
| 35 | 1 | 6 | 1 | 43 |
| 31 | 1 | 7 | 1 | 62 |
| 44 | 1 | 8 | 0 | 0 |
| 32 | 1 | 9 | 0 | 5 |
| 35 | 1 | 12 | 1 | 30 |
Results 表记录每个回答问题的结果,并为回答时间加上时间戳,因此该表可以为用户回答的每个问题提供许多记录,看起来像这样(其他列已删除)
结果
| resultID | userID | topicID | qID | correct | answerTime |
| 9 | 1 | 12 | 15 | 1 | 2020-05-28 11:29:18 |
| 10 | 1 | 12 | 26 | 1 | 2020-05-28 11:30:18 |
| 11 | 1 | 1 | 132 | 0 | 2020-06-02 17:03:42 |
| 13 | 1 | 2 | 50 | 0 | 2020-06-02 17:02:53 |
| 14 | 1 | 7 | 10 | 1 | 2020-06-02 17:05:15 |
| 76 | 1 | 6 | 9 | NULL | 0000-00-00 00:00:00 |
| 75 | 1 | 6 | 9 | NULL | 0000-00-00 00:00:00 |
| 65 | 1 | 9 | 12 | NULL | 0000-00-00 00:00:00 |
| 66 | 1 | 9 | 12 | 1 | 2020-06-04 07:34:02 |
为了让系统自动为学生分配问题,我们需要特定用户当前正在学习的每个 topicID 的 topicScore 和 answerTime 值。必须为 UserTopics 表中的每个 topicID 返回一行,其中用户的 tFlag = 1。然后应该从结果表中获取从 userTopics 返回的每个 topicID 的最新 answerTime。但是,如果为特定 topicID 列出的唯一 answerTime 是 0000-00-00 00:00:00,我需要返回它。 (answerTime col 使用 ON UPDATE CURRENT_TIMESTAMP,所以如果他们已经加载了问题但没有回答它,这里的值是零。)
userID = 1 的查询结果希望是:
查询结果
| topicID | topicScore | answerTime |
| 1 | 25 | 2020-06-02 17:03:42 |
| 2 | 70 | 2020-06-02 17:02:53 |
| 6 | 43 | 0000-00-00 00:00:00 |
| 7 | 62 | 2020-06-02 17:05:15 |
| 12 | 30 | 2020-06-04 07:34:02 |
我已经尝试了以下查询,但它没有得到我想要的,也没有真正理解它,因为我对 mysql 的掌握有点基本 atm。 (另一个人写的查询)
SELECT
r.userID,
r.topicID,
r.answerTime,
(SELECT t.topicScore FROM UserTopics t WHERE t.userID = r.userID AND t.topicID = r.topicID) AS topicScore
FROM Results r
LEFT JOIN Results r2 ON r2.topicID = r.topicID AND r.answerTime < r2.answerTime
WHERE r2.answerTime IS NULL AND r.userID = 1
ORDER BY `r`.`topicID` ASC
我可以看到它需要在某处有 Where t.tFlag =1,但是当我将它放在方括号中的 where 子句中时,它也不起作用,所以我假设整个查询需要重写。很高兴得到任何帮助。
【问题讨论】:
见meta.***.com/questions/333952/… 【参考方案1】:这是我现在按照以下 O Jones 建议尝试和测试的查询....需要进行一些更改,但核心正是医生所要求的,就像一个魅力一样,谢谢。每个查询只需要一个 userID,并且只需要 topicScores 不为 0 的结果。此外,由于 UserTopics 表中每个 topicID 只有一行,因此也不需要 MAX 语句。
SELECT ut.topicId,
ut.topicScore,
MAX(r.answerTime) answerTime
FROM UserTopics ut
LEFT JOIN Results r ON ut.userId = r.userId
AND ut.topicId = r.topicId
WHERE ut.tFlag =1 AND ut.userId = 1 AND ut.topicScore >0
GROUP BY ut.topicId
ORDER BY ut.topicId
【讨论】:
【参考方案2】:首先,使用零日期戳会使设计变得脆弱。更高版本的 MySQL 不允许零日期戳。您需要发出此命令才能使事情正常进行,即删除NO_ZERO_DATE
模式。
SET sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
您最好使用 NULL 而不是零日期戳。话说……
这是GROUP BY
的工作,您可以从中提取 userId 和 topicId 的每个组合的最高分数和 answerTime。 (https://www.db-fiddle.com/f/swC1jG2mMHRsAkCouJNfXq/5)
SELECT ut.userId, ut.topicId,
MAX(ut.topicScore) topicScore,
MAX(r.answerTime) answerTime
FROM UserTopics ut
LEFT JOIN Results r ON ut.userId = r.userId
AND ut.topicId = r.topicId
WHERE ut.tFlag =1
GROUP BY ut.userId, ut.topicId
ORDER BY ut.userId, ut.topicId
【讨论】:
将与您的建议一起使用 NULL 而不是零时间戳谢谢。我已经修改了您的答案以解决几个问题,因为我只想要每个查询的一个用户 ID 的一组结果,并且只需要 topicScore 不为零的 topicID。我已将调整后的查询放在下面的答案中,但您已经破解了 O Jones 先生!非常感谢。以上是关于从表中选择最新的带时间戳的值,该表对于一个列 id 有多个条目,对于每个唯一的列 id 和来自另一个表的数据的主要内容,如果未能解决你的问题,请参考以下文章