【问题标题】:Displaying records with a column value 0 when there is no record没有记录时显示列值为 0 的记录
【发布时间】:2013-01-09 06:26:12
【问题描述】:

我有以下表格:

架构

tbl_semester_empid {id,semester_name varchar(50),start_date}

tbl_batch_empid {id、semester_id、batch_name、session_room}

tbl_associate_empid {id, associate_name, batch_id, contact, join_date,duction_result, stream_result int}

问题查询是:显示学期明智的员工人数。

我写了 3 个查询:

--basic query
SELECT s.ID "Semester Id", COUNT(*) "Associate Count" FROM TBL_SEMESTER_593932 s, TBL_ASSOCIATE_593932 a, TBL_BATCH_593932 b 
        WHERE s.ID=b.SEMESTER_ID AND a.BATCH_ID=b.ID  
                GROUP BY s.ID;

--used NVL function
SELECT s.ID "Semester Id", NVL(COUNT(*),0) "Associate Count" FROM TBL_SEMESTER_593932 s, TBL_ASSOCIATE_593932 a, TBL_BATCH_593932 b 
        WHERE s.ID=b.SEMESTER_ID AND a.BATCH_ID=b.ID  
                GROUP BY s.ID;

-- used LEFT OUTER JOIN and  JOIN
SELECT s.ID "Semester Id", NVL(COUNT(*),0) "Associate Count" 
        FROM TBL_SEMESTER_593932 s LEFT OUTER JOIN TBL_BATCH_593932 b ON s.ID=b.SEMESTER_ID 
             JOIN TBL_ASSOCIATE_593932 a ON a.BATCH_ID=b.ID  
                   GROUP BY s.ID;

全部显示如下输出(只显示至少有1个学生的学期对应的记录,如果该学期没有学生,则不显示该学期的信息):

我希望在 Associates Count 列中没有员工的学期为 0。所以我用两个 LEFT OUTE JOIN 尝试了同样的方法:

SELECT s.ID "Semester Id", NVL(COUNT(*),0) "Associate Count" 
    FROM TBL_SEMESTER_593932 s LEFT OUTER JOIN TBL_BATCH_593932 b ON s.ID=b.SEMESTER_ID 
         LEFT OUTER JOIN TBL_ASSOCIATE_593932 a ON a.BATCH_ID=b.ID  
                GROUP BY s.ID;

但是结果很奇怪:

【问题讨论】:

    标签: sql oracle join left-join nvl


    【解决方案1】:

    基本上,您要做的就是使用所有可用学期的列表,然后计算每个学期的金额:

    select s.ID, 
           s.Semester_Name,
           NVL ((select count(*) 
              from TBL_ASSOCIATE_593932 a
                   join TBL_BATCH_593932 b 
                     on a.BATCH_ID=b.ID
            where  s.ID=b.SEMESTER_ID
           ),0) as Amount
     from TBL_SEMESTER_593932 s
    

    另一种方法是加入您的所有学期列表,然后计算

    select s.ID, 
           s.Semester_Name,
           count(*) as Amount 
     from TBL_SEMESTER_593932 s
            left join (
              TBL_BATCH_593932 b
              join TBL_ASSOCIATE_593932 a  
                on a.BATCH_ID=b.ID)
               on s.ID=b.SEMESTER_ID
    
    group by s.ID, s.Semester_Name
    order by s.ID
    

    [编辑]:根据@Mahesha999 更正了最后一个查询。

    【讨论】:

    • 第一个查询很棒,它正在按照预期的方式工作,但第三个我认为格式不正确,应该是from TBL_SEMESTER_593932 s left join **TBL_BATCH_593932 b** on s.ID=b.SEMESTER_ID join **TBL_ASSOCIATE_593932 a** on a.BATCH_ID=b.ID。但是,这与我上次的查询相似,并且不显示没有学生的学期记录
    • @Mahesha999:感谢您向我显示错误:我相应地更正了查询。
    • 但它仍然没有显示没有关联的学期记录:(
    • 嗯,我实现了你的建议。不管怎样,试试这个方法。我使用大括号来确保所有学期都被列出。
    • 从逻辑上讲,您也不需要在这里使用 NVL - 只是为了性能,对吗? @alzaimar 无论如何感谢您的第一个查询
    【解决方案2】:

    您尝试过使用CASE when 吗?

    根据您的关联表中的数据,所有批次/学期都有记录。

    所以试试这个,你的 NVL 和 case 很相似……

    select s.id, s.name, CASE WHEN count(a.id) IS NULL THEN 0 ELSE count(a.id) END as ACount
    from tblsem s
    left join tblbatch b
    on b.sid = s.id
    left join tblaso a
    on b.id = a.batchid
    group by s.id, s.name
    ;
    

    结果:

    ID  NAME    ACOUNT
    1   sem1    4
    2   sem2    3
    3   sem3    0
    

    【讨论】:

    • 添加了Schema,只看原始问题,会尝试CASE时,更新
    • 想不出应该如何使用CASE,一个很好的例子是here,但还是想不出来
    • @Mahesha999 忘记大小写。 :) 因为 Oracle NVL 也这样做.. 但试试看。我还会为您提供一些其他信息。
    • @Mahesha999 请查看 sqlfiddle 参考和评论。我使用了自己的一些示例数据来向您展示逻辑。在我的 sql 中,您可以使用 coalesce 函数,该函数与 oracle 中的 NVL 相同,但我使用的是 case ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-12
    • 2017-04-29
    • 1970-01-01
    相关资源
    最近更新 更多