按关联记录的条件计数排序

Order by conditional count of associated records

一个quiz可以有none,一个或多个submissions。每个 submissionsubmissions.correct = tsubmissions.correct = f.

获取所有 quizzes 的最佳 Postgres 9.4 查询是什么(无论它们是否具有 Submission),按关联的 submissions 和 [=19] 的数量排序=] 以 ASC 顺序排列,以便具有最少关联 submissions.correct = tquizzes 排在第一位?

db=# \d quizzes;
                                         Table "public.quizzes"
       Column   |            Type             |                      Modifiers                       
    ------------+-----------------------------+------------------------------------------------------
     id         | integer                     | not null default nextval('quizzes_id_seq'::regclass)
     question   | character varying           | not null
     created_at | timestamp without time zone | not null
     updated_at | timestamp without time zone | not null
    Indexes:
        "quizzes_pkey" PRIMARY KEY, btree (id)
    Referenced by:
        TABLE "submissions" CONSTRAINT "fk_rails_04e433a811" FOREIGN KEY (quiz_id) REFERENCES quizzes(id)
        TABLE "answers" CONSTRAINT "fk_rails_431b8a33a3" FOREIGN KEY (quiz_id) REFERENCES quizzes(id)

db=# \d submissions;
                                         Table "public.submissions"
       Column   |            Type             |                        Modifiers                         
    ------------+-----------------------------+----------------------------------------------------------
     id         | integer                     | not null default nextval('submissions_id_seq'::regclass)
     quiz_id    | integer                     | not null
     correct    | boolean                     | not null
     created_at | timestamp without time zone | not null
     updated_at | timestamp without time zone | not null
    Indexes:
        "submissions_pkey" PRIMARY KEY, btree (id)
        "index_submissions_on_quiz_id" btree (quiz_id)
    Foreign-key constraints:
        "fk_rails_04e433a811" FOREIGN KEY (quiz_id) REFERENCES quizzes(id)
SELECT q.*, s.ct
FROM   quizzes q
LEFT   JOIN (
   SELECT quiz_id, count(*) AS ct
   FROM   submissions
   WHERE  correct
   GROUP  BY 1
   ) s ON s.quiz_id = q.id
ORDER BY s.ct NULLS FIRST;
  • 因为你想要所有测验,所以先聚合然后加入可能是最快的。
  • 将其设置为 LEFT JOIN 以在结果中保留没有提交的测验。
  • NULLS FIRST 在这里至关重要,因此没有任何(正确)提交的测验首先出现。
    • PostgreSQL sort by datetime asc, null first?
  • 与其他一些流行的 RDBMS 不同,Postgres 有一个合适的 boolean 类型。表达式 correct = tcorrect.
  • 完全相同