postgres 等级函数的使用

postgres use of rank function

我是 Sql 查询的新手。我需要构建一个查询,该查询将根据学生获得 100% 的测试次数除以他参加的测试总数来对学生进行排名,并且只考虑 10 天前的测试。这是我的 table 结构。

CREATE TABLE student(
id serial NOT NULL,student_email varchar NULL,
student_name varchar NULL,
test_subject varchar NULL,
total_question varchar NULL,
total_passed varchar NULL,
total_failed varchar NULL,
total_skipped varchar NULL,
test_time timestamp NULL,
CONSTRAINT student PRIMARY KEY (id));

如果学生的 total_failed 或 total_skipped 不是 0,则该测试不被视为具有 100%。

示例数据将类似于

1   j@b.com john    maths   10  10  0   0   2019-08-20 21:00:00
2   j@b.com john    maths   10  10  0   0   2019-08-19 21:00:00
3   j@b.com john    maths   10  09  1   0   2019-08-18 21:00:00
4   j@b.com john    english 10  10  0   0   2019-08-20 21:00:00
5   j@b.com john    english 10  10  0   0   2019-08-19 21:00:00
6   j@b.com john    english 10  09  0   1   2019-08-20 21:00:00
7   p@b.com paul    maths   10  10  0   0   2019-08-20 21:00:00
8   p@b.com paul    maths   10  10  0   0   2019-08-19 21:00:00
9   p@b.com paul    maths   10  10  0   0   2019-08-18 21:00:00
10  k@b.com koki    maths   10  10  0   0   2019-06-20 21:00:00
11  k@b.com koki    english 10  10  0   0   2019-06-20 21:00:00
12  k@b.com koki    science 10  10  0   0   2019-08-20 21:00:00
13  k@b.com koki    maths   10  08  2   0   2019-08-20 21:00:00
14  k@b.com koki    english 10  10  0   0   2019-08-20 21:00:00

从上述数据集中,我只需要考虑 10 天内的那些数据,并根据测试总数 100% 除以每个不同 [的测试总数得出 "RANK" =26=],学生。 以上数据集的输出将是

koki    science 100%   k@b.com
koki    english 100%   k@b.com
paul    maths   100%   p@b.com
john    maths   66.6%  j@b.com
john    english 66.6%  j@b.com
koki    science 0%     k@b.com

感谢任何帮助

您可以使用条件聚合。在这种情况下,avg() 应该有效:

select student_name, test_subject,
       avg( (total_failed + total_skipped = 0)::int ) as ratio_passed
from t
where test_time > now() - interval 10 day
group by student_name, test_subject;

当我

  • 翻译你对rank的定义:

    total number of test with 100% divided by total number of test

    作为

    COUNT(*) FILTER (WHERE total_passed = total_question) / COUNT(*)::real
    
  • 并应用最近 10 天的过滤器:

    test_time > CURRENT_DATE - interval '10 days'
    

我最终得到以下查询

SELECT  
  student_name
, test_subject
, COUNT(*) FILTER (WHERE total_passed = total_question) / COUNT(*)::real student_rank

FROM student 
WHERE test_time > CURRENT_DATE - interval '10 days' 
GROUP BY 1, 2 
ORDER BY 3 desc;

我得到了想要的输出:

 student_name | test_subject |   student_rank
--------------+--------------+-------------------
 paul         | maths        |                 1
 koki         | english      |                 1
 koki         | science      |                 1
 john         | maths        | 0.666666666666667
 john         | english      | 0.666666666666667
 koki         | maths        |                 0
(6 rows)