SQL 一对多关系表的统计 的更优解是什么?

2019-06-24 17:08:03 +08:00
 iugo

比如问题是: 成绩达到过 80 以上的同学有几位?

示例表:

table test_students
name | studentID
Jim  | 1001

table test_scoresheet
studentID | date       | score
1001      | 2019-09-24 | 81
1001      | 2019-10-24 | 85

以 PostgreSQL 为例:

创建测试表及数据:

CREATE TABLE "public"."test_students" ("studentID" serial,"name" text, PRIMARY KEY ("studentID"));
INSERT INTO "public"."test_students" ("studentID", "name") VALUES ('1001', 'Jim');

CREATE TABLE "public"."test_scoresheet" ("id" serial,"studentID" int4, "date" text, "score" int4, PRIMARY KEY ("id"));
INSERT INTO "public"."test_scoresheet" ("id", "studentID", "date", "score") VALUES ('1', '1001', '2019-09-24', '81');
INSERT INTO "public"."test_scoresheet" ("id", "studentID", "date", "score") VALUES ('2', '1001', '2019-10-24', '85');

已知但预计不够良好的解法:

SELECT COUNT(id) FROM (
	SELECT
		DISTINCT ON(test_students."studentID")
		test_students."studentID" AS id
	FROM test_students
		INNER JOIN test_scoresheet ON test_students."studentID" = test_scoresheet."studentID"
) AS some_students;
1382 次点击
所在节点    问与答
5 条回复
dingz
2019-06-24 18:27:11 +08:00
select count(*) from test_student WHERE studentID IN (select studentID FROM test_scoresheet where score>80)
akira
2019-06-24 18:34:25 +08:00
对 studentID 做去重 汇总就好了啊 , test_students 表都不需要
iugo
2019-06-25 17:10:16 +08:00
@dingz 如果 test_scoresheet 量级是百万, 不知道哪种做法效率更高.
iugo
2019-06-25 17:11:10 +08:00
@akira 是我的例子不够好, 实际上是需要统计 test_students 中的一些数据的, 不是简单地记数.
akira
2019-06-25 18:49:21 +08:00
@iugo 那就是 1l 的写法,加个 distinct,或者考虑在内嵌个 max 子查询.

如果你的写法 没有出现性能问题,其实也不需要去管太多的,
能出正确结果的 sql 就是好 sql

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/576990

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX