postgresql - 使用 distinct + 过滤器时选择特定行的最快查询
问题描述
表答案:
Answer ID | User ID | Question ID | deleted
1 | 1 | 1 | f
2 | 1 | 2 | f
3 | 1 | 2 | f
4 | 1 | 1 | t
5 | 2 | 1 | f
6 | 2 | 2 | f
7 | 2 | 2 | f
我想选择所有与(userID, questionID)
使用最新答案(基于最高 id)不同的答案,并从这个结果集中删除所有具有deleted = t
.
所以我的结果应该是
Answer ID | User ID | Question ID | deleted
3 | 1 | 2 | f
5 | 2 | 1 | f
7 | 2 | 2 | f
我想我们无法使用从界面生成的查询方法来做到这一点?我正在使用@Query
注释:
@Query("SELECT a1 FROM answer a1 WHERE ... ")
findLatestAnswers();
我想出了这个(sql fiddle:http ://sqlfiddle.com/#!15/02339/8/0 ),甚至没有使用distinct
or group by
nor order by
。它正在完成这项工作,但对于更大的数据集似乎效率很低?什么是更快的声明?
SELECT * FROM answer a1
WHERE NOT EXISTS ( -- where no newer answer exists
SELECT * FROM answer a2
WHERE a1.user_id = a2.user_id
AND a1.question_id = a2.question_id
AND a1.id < a2.id
)
AND a1.deleted = FALSE;
解决方案
distinct
使用orgroup by
或聚合函数没有问题。这些在数据仓库或分析软件中是必不可少的,在这些软件中,每个请求都会处理数百万或记录(数十亿和数万亿的大数据)。
唯一的调整是根据您的数据和查询生成索引。
您的 scanrio 所需的功能是max
. 您必须选择分组max
如下:anser_id
user_id, question_id
解决方案 1
@Query("select max(answer) from Answer answer where answer.deleted = false group by answer.userId, answer.questionId")
List<Answer> findLatestAnswersByUserQuestionNotDeleted();
该语句返回 4 条记录,因为如果您不考虑删除答案,则问题 1 中用户 1 的最新答案将变为 1。
我不知道您为什么不考虑这一点,但我会照原样关注您的问题。
因此,您必须按照您的描述以编程方式删除过滤器,因此@Query
变为:
@Query("select max(answer) from Answer answer group by answer.userId, answer.questionId")
List<Answer> findLatestAnswersByUserQuestion();
再次正确地,您有 4 条记录,因为也存在已删除并且必须以编程方式过滤
解决方案2(两个查询,因为您要求忽略已删除而不考虑旧的)
第 1 步 - findId 的答案,包括已删除(仅 id):
@Query("select max(answer.id) from Answer answer group by answer.userId, answer.questionId")
List<Long> findLatestAnswersId();
第 2 步 - 按 id 加载答案,不包括已删除
List<Answer> findAllByDeletedIsFalseAndIdIn(List<Long> ids);
解决方案 3(一个查询)
@Query("select answer from Answer answer where answer.deleted = false and answer.id in (select max(inAnswer.id) from Answer inAnswer)")
List<Answer> findLastestNotDeleted()
推荐阅读
- tpm - 用裤子将 SRK 存储在 TPM 上
- r - 从 R 上传 winbugs 中的数据集
- python - Python3 中的 *args 是否保证保持顺序?
- html - 在 HTML 中创建按钮以进行更新
- openshift - OpenShift 上的 RHEL Atomic Image:安装安全更新
- c# - 状态码:500 内部服务器错误
- java - 无法将 xs:string 与 xs:integer 进行比较
- python - 如何在Jinja2模板中将项目填充到两列
- react-native - 如何在平面列表中获得带有部分标题的水平列表视图
- php - 如何将 SAML 设置为多个域?