从每组中的 3 个表中选择 sql 中具有最新日期的行
Posted
技术标签:
【中文标题】从每组中的 3 个表中选择 sql 中具有最新日期的行【英文标题】:select rows in sql with latest date from 3 tables in each group 【发布时间】:2020-06-29 04:35:34 【问题描述】:我正在为我的应用程序创建 PREDICATE 系统。
请看我已经看过的图片
我有一个问题,如何在 SQL 中为每个“QuizESId”列选择具有最新日期“Taken On”列表的行,在此之前我了解如何选择它,但它只使用一个表,我从中学习 select rows in sql with latest date for each ID repeated multiple times
这是我已经尝试过的
SELECT tt.*
FROM myTable tt
INNER JOIN
(SELECT ID, MAX(Date) AS MaxDateTime
FROM myTable
GROUP BY ID) groupedtt ON tt.ID = groupedtt.ID
AND tt.Date = groupedtt.MaxDateTime
我这里比较困惑的是如何从3个表中进行选择,希望您能指导我,当然我需要一个查询良好且性能高效的解决方案。
谢谢
【问题讨论】:
您可以在“Taken On”列中使用order by。 Bad habits to kick : using old-style JOINs - 旧式 逗号分隔的表格列表 样式已替换为 ANSI 中的 proper ANSIJOIN
语法-92 SQL 标准(25 多年前),不鼓励使用它
@marc_s 谢谢你的建议,我知道使用旧样式是不可读的,但是性能如何,和加入一样吗?
感谢@marc_s,它真的是很好的指导,我从中得到了很多。回到我的问题,你能回答我的问题吗
您使用的是哪种 DBMS 产品? “SQL”只是一种查询语言,而不是特定数据库产品的名称。 Why should I tag my DBMS
【参考方案1】:
这适用于 SQL Server(您没有具体说明您使用的是什么 RDBMS):
如果您想获得“每个 QuizId
的最新行” - 这听起来像您需要具有 ROW_NUMBER()
值的 CTE(公用表表达式) - 类似这样(更新: 你显然想“分区”不只是QuizId
,还需要UserName
):
WITH BaseData AS
(
SELECT
mAttempt.Id AS Id,
mAttempt.QuizModelId AS QuizId,
mAttempt.StartedAt AS StartsOn,
mUser.UserName,
mDetail.Score AS Score,
RowNum = ROW_NUMBER() OVER (PARTITION BY mAttempt.QuizModelId, mUser.UserName
ORDER BY mAttempt.TakenOn DESC)
FROM
UserQuizAttemptModels mAttempt
INNER JOIN
AspNetUsers mUser ON mAttempt.UserId = muser.Id
INNER JOIN
QuizAttemptDetailModels mDetail ON mDetail.UserQuizAttemptModelId = mAttempt.Id
)
SELECT *
FROM BaseData
WHERE QuizId = 10053
AND RowNum = 1
BaseData
CTE 基本上选择数据(就像您所做的那样) - 但它也添加了一个 ROW_NUMBER()
列。这会将您的数据“分区”为数据组 - 基于 QuizModelId
- 并且它将对每个数据组内的所有行进行编号,从 1 开始,并按第二个条件 - ORDER BY
子句排序。您说您想按“开始”日期订购 - 但在您的查询中没有显示这样的日期 - 所以我只是猜测它可能在 UserQuizAttemptModels
表上 - 根据需要进行更改和调整。
现在,您可以使用原始 WHERE
条件从该 CTE 中进行选择 - 并且您指定,您只需要每个数据组(对于每个“QuizId”)的第一行 - 具有最新“开始”的那一行" 日期值。
【讨论】:
我从 Mike Hernandez 的 Database Design fo Mere Mortals 那里学到了 DB 设计的基础知识。对于性能调优,我强烈推荐 Grant Fritchey 的 SQL Server 2017 Query Performance Tuning: Troubleshoot and Optimize Query Performance。 此查询将执行良好如果您有适当的索引 - 任何外键列都应该被索引,如果您有WHERE
子句,该列 (或那些列)如果可能的话也应该被索引。但它也将在很大程度上取决于您的数据 - 数据的多少,数据的“形状”是什么。性能是一个非常复杂的主题 - 除非您可以实际处理具体数据,否则不容易处理......
不太确定我是否理解您的问题。也许您对构成“数据组/分区”的定义不完整?也许您需要改用PARTITION BY QuizModelId, mUser.UserName
? (如果我正确理解了你想要做什么......)
哦,是的,感谢您的书籍建议,我会购买并学习,希望能像您一样成为专家
正如我所说 - 您需要分区不仅是 QuizId,还需要“姓名” - 试试这个:ROW_NUMBER() OVER (PARTITION BY mAttempt.QuizModelId, mUser.UserName
- 会返回正确的结果吗? 以上是关于从每组中的 3 个表中选择 sql 中具有最新日期的行的主要内容,如果未能解决你的问题,请参考以下文章