【问题标题】:SQL query for database find the nr of students数据库的 SQL 查询找到学生的 nr
【发布时间】:2020-02-06 20:39:58
【问题描述】:

我是数据库的初学者,我有以下几点:我需要展示那些不正确学生数量最多的课程(所以那些还没有带来这本书的人以及那些迟于 date_to_return 带来的人)

  1. 表格课程:课程代码、课程名称。

  2. 表格pupils_on_courses:学生id、课程代码。

  3. 表格学生:学生id

  4. books_out_on_loan:学生id、isbn、date_borrowed、date_to_return_date_returned

我试图找到每个部分的不正确学生的数量,但现在我坚持找到最大值。

我认为错误在于我计算date_returneddate_to_return的条件

select 
    c.course_code, c.course_name, count (bb.pupil_id) 
from 
    courses c 
inner join 
    pupils_on_courses ps on c.course_code = ps.course_code
inner join 
    pupils p on p.pupil_id = ps.pupil_id
inner join 
    books_out_on_loan bb on p.pupil_id = bb.pupil_id
group by 
    c.course_code, c.course_name
having 
    count (bb.pupil_id) = (select max(count(*))
                           from pupil p 
                           inner join books_out_loan bb on p.pupil_id = bb.pupil_id
                           where bb.date_returned is null 
                              or bb.date_returned > date_to_return
                           group by c.course_code, c.course_name) 

感谢您的帮助

编辑: 一些示例数据将是:

【问题讨论】:

  • pupilsbooks_out_on_loan 之间的 JOIN 应该是 LEFT JOIN,不是吗?
  • 我也尝试了左连接...仍然是相同的结果@Shiva
  • 如果您在 sqlfiddle.com 上发布一些示例架构和数据,也许有人可以提供帮助...
  • 子查询中不需要课程名称。
  • 你也不能嵌套聚合函数。

标签: sql database


【解决方案1】:
select 
    c.course_code, min(c.course_name) course_name,
    count(distinct pc.pupil_id) as max_pupil_cnt
from 
    courses c inner join pupils_on_courses pc
        on ps.course_code = c.course_code
    inner join books_out_on_loan b
        on b.pupil_id = pc.pupil_id
where b.date_returned is null or b.date_returned > b.date_to_return
group by c.course_code
having count (distinct pc.pupil_id) >= all (
    select count(distinct pc2.pupil_id)
    from pupils_on_courses pc2 inner join books_out_loan b2. 
        on b2.pupil_id = pc2.pupil_id
    where b2.date_returned is null or b2.date_returned > b2.date_to_return
    group by pc2.course_code
);

有现代方法可以做到这一点,而无需重复逻辑。我的猜测是你需要坚持基本的东西,因为这看起来像是家庭作业。

【讨论】:

    【解决方案2】:

    如果您发布示例数据,我们可以更轻松地提供帮助。

    如果您想要计算学生人数而不是未购买书籍或延迟退货的数量,这可能对您有用:

    select 
        c.course_code, c.course_name, 
        count (distinct case when bb.date_returned is null or bb.date_returned > date_to_return
          then p.pupil_id else null end) as NoncorrectStudents
    from 
        courses c 
    inner join 
        pupils_on_courses ps on c.course_code = ps.course_code
    inner join 
        pupils p on p.pupil_id = ps.pupil_id
    left join 
        books_out_on_loan bb on p.pupil_id = bb.pupil_id
    group by 
        c.course_code, c.course_name
    

    一旦你有了这个,你应该能够按不正确学生的数量进行排序。请在有机会时发布数据,以便验证。

    【讨论】:

    • 谢谢@JJ32 我刚刚编辑了上面的一些示例数据
    • 我没有意识到这是甲骨文。将来,请适当地使用标签(有关指南,请参阅stackoverflow.com/help/how-to-ask)。我将在上面窃取@LukStorms 的想法,因为 Oracle 允许您使用窗口函数,您可以使用 Rank() 来获得不正确学生的课程的最高结果。在任何一种情况下,学生的数量(不同)都应该让你进入正确的范围(我无法测试,因为我不是 Oracle 用户)。
    【解决方案3】:

    您可能已经在WHERE 子句中过滤了“不正确”。

    那么它不会返回那些只有“正确”的。
    但是,由于您只想要那些具有最大“不正确”的人,因此应该足够公平。

    而且您可能还需要仅选择那些必须在当前日期之前返回的那些。

    SELECT c.course_code, c.course_name
    , COUNT(DISTINCT bb.pupil_id) AS non_correct_pupils
    FROM books_out_on_loan bb 
    INNER JOIN pupils_on_courses ps 
      ON ps.pupil_id = bb.pupil_id
    INNER JOIN courses c 
      ON c.course_code = ps.course_code
    WHERE bb.date_to_return < CAST(current_timestamp AS DATE)
    AND (bb.date_returned IS NULL OR bb.date_returned > bb.date_to_return)
    GROUP BY c.course_code, c.course_name
    ORDER BY COUNT(DISTINCT bb.pupil_id) DESC
    

    DISTINCT 仅用于计算唯一的学生 ID。

    要获得最高排名,试试这个

    SELECT * 
    FROM
    (
    SELECT c.course_code, c.course_name
    , COUNT(DISTINCT bb.pupil_id) AS non_correct_pupils
    , DENSE_RANK() OVER (ORDER BY COUNT(DISTINCT bb.pupil_id) DESC) AS Rnk
    FROM books_out_on_loan bb 
    INNER JOIN pupils_on_courses ps 
      ON ps.pupil_id = bb.pupil_id
    INNER JOIN courses c 
      ON c.course_code = ps.course_code
    WHERE bb.date_to_return < CAST(current_timestamp AS DATE)
    AND (bb.date_returned IS NULL OR bb.date_returned > bb.date_to_return)
    GROUP BY c.course_code, c.course_name
    )
    WHERE Rnk = 1
    

    【讨论】:

    • 是的,我在工作的中间完成了这个,但我想显示它们中的最大值,我的意思是,例如可能有 3 个部分的学生不正确,但是只有一个部分具有最大的 nr。我想输出它,而不考虑其他的。或者即使两个部分可以有相同的 nr 个不正确的学生,但只要是其他部分中最大的,那应该是输出。这可以用max完成吗?如何? @LukStorms
    • 不确定部分是什么意思。而且您没有标记您使用的数据库/版本的类型。但是要获得最高排名,那么一种方法是计算DENSE_RANK() OVER (ORDER BY COUNT(DISTINCT bb.pupil_id) DESC) AS Rnk。将查询包装在子查询中。然后选择 Rnk = 1 的那些。
    • 我正在使用 sql 开发者@LukStorms
    • Oracle SQL 开发者?那是一个工具,而不是 DBMS。但是甲骨文也有windows functions。所以试试 DENSE_RANK。
    • 如我所说...我是初学者
    猜你喜欢
    • 2020-02-27
    • 2014-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多