无法显示0表示空值

时间:2011-05-11 18:33:20

标签: sql count

当答案为空时,我在结果中返回值0时遇到问题,我的当前代码如下。

select distinct bt2.isbn, bt2.btname, Count ('bcid')

from 
booktitle bt1, booktitle bt2,
bookcopy bc1, bookcopy bc2, 
loan l1, loan l2

where
bt1.isbn = bc1.isbn
and bc1.bcid = l1.bcid
and l1.bcid = l2.bcid
and l2.bcid = bc2.bcid
and bc2.isbn = bt2.isbn


group by  bt2.isbn, bt2.btname

order by Count ('bcid') desc;

如何获得结果答案以显示值0,而由于空值,它们当前没有返回行。我曾尝试使用以前回答的问题来帮助我,但似乎无法掌握这个概念。任何和所有帮助将不胜感激


使用迄今为止提供的所有帮助我已经提出了这个代码

select bt1.isbn, bt1.btname, Count (bc.bcid)    


from booktitle bt1
  inner join bookcopy bc
   on bc.isbn = bt1.isbn
  inner join loan l
   on l.bcid = bc.bcid

  left outer join Bookcopy bc2
   on bc2.isbn = bt1.isbn

 group by  bt1.isbn, bt1.btname
 order by Count (2bc.bcid) desc;

然而,它似乎仍然只返回计数大于0的行,是否有办法使它返回count = 0的行以及计数更大的行?

2 个答案:

答案 0 :(得分:4)

基于内部联接的查询只会在数据存在时生成行。例如,如果“bt2”中的行在“bt1”中没有匹配的连接,那么您将不会在最终集合中获得这些bt2行。

即使没有匹配的bt1,要生成一个包含(比如说)所有bt2的集合,你需要使用外连接。修改你的代码以使用ON子句(除了强制性的,如果你要使用外连接),你就可以切换

from booktitle bt2
 inner join bookcopy bc2
  on bc2.isbn = bt2.isbn
 inner join loan l2
  on l2.bcid = bc2.bcid
 inner join loan l1
  on l1.bcid = l2.bcid
 inner join bookcopy bc1
  on bc1.bcid = l1.bcid
 inner join Booktitle bt1
  on bt1.isbn = bc1.isbn

from booktitle bt2
 inner join bookcopy bc2
  on bc2.isbn = bt2.isbn
 inner join loan l2
  on l2.bcid = bc2.bcid
 inner join loan l1
  on l1.bcid = l2.bcid
 inner join bookcopy bc1
  on bc1.bcid = l1.bcid
 LEFT OUTER JOIN Booktitle bt1
  on bt1.isbn = bc1.isbn

这将产生包含所有bt2数据的行(假设所有那些介入的内连接都已计算出来),bt1结果集中没有数据 - 由NULL表示。通过计算bt1集合中的列来限制它,你应该得到你的零:

SELECT distinct bt2.isbn, bt2.btname, Count (bt1.isbn)    
 from booktitle bt2
  inner join bookcopy bc2
   on bc2.isbn = bt2.isbn
  inner join loan l2
   on l2.bcid = bc2.bcid
  inner join loan l1
   on l1.bcid = l2.bcid
  inner join bookcopy bc1
   on bc1.bcid = l1.bcid
  left outer join Booktitle bt1
   on bt1.isbn = bc1.isbn
 group by  bt2.isbn, bt2.btname
 order by Count (bt1.isbn) desc

答案 1 :(得分:1)

重构原始查询以使用正确的连接语法给我这个:

select bt2.isbn   ,
       bt2.btname ,
       Count ('bcid')
from booktitle bt1 ,
join bookcopy  bc1 on bc1.isbn = bc1.isbn 
join loan      l1  on l1.bcid  = bc1.bcid
join loan      l2  on l2.bcid  = l1.bcid
join bookcopy  bc2 on bc2.bcid = l2.bcid
join booktitle bt2 on bt2.bcid = bc2.bcid
group by  bt2.isbn, bt2.btname
order by Count ('bcid') desc

仍然无法确切地说明您要完成的任务。但是,如果我们扩展您的查询以全面使用左连接,那么

select *
from      booktitle bt1
left join bookcopy  bc1 on bc1.isbn = bc1.isbn 
left join loan      l1  on l1.bcid  = bc1.bcid
left join loan      l2  on l2.bcid  = l1.bcid
left join bookcopy  bc2 on bc2.bcid = l2.bcid
left join booktitle bt2 on bt2.bcid = bc2.bcid

对于booktitle中的每个条目,您将获得至少一行:任何不匹配的连接都将其所有列设置为null,这将沿着连接链向下传播(如果您的SQL引擎符合标准)null失败所有测试保存通过is [not] null表示对无效的测试。这给了我们我们的候选集,我们需要总结一下。与整个连接链匹配的行将具有bt2的非空列;这些列将包含与整个连接链不匹配的行的所有null值。

您希望计算bt1中与isbn / btname分隔的整个连接链中的条目数。为此,我们添加了我们需要的分组列以及我们需要的聚合函数。根据我对原始查询的理解(例如),我相信以下将会做到这一点:

select bt1.isbn   ,
       bt1.btname ,
       sum( case when bt2.bcid is not null then 1 else 0 end )
from      booktitle bt1
left join bookcopy  bc1 on bc1.isbn = bc1.isbn 
left join loan      l1  on l1.bcid  = bc1.bcid
left join loan      l2  on l2.bcid  = l1.bcid
left join bookcopy  bc2 on bc2.bcid = l2.bcid
left join booktitle bt2 on bt2.bcid = bc2.bcid
group by  bt1.isbn, bt1.btname
order by 3 desc ,
         1 ,
         2

你会注意到sum(case...end),其中case表达式作为判别函数,产生可以计算的0/1值;通过简单的count(tb2.bcid)可以获得相同的结果,因为除了count(*)之外,汇总函数不会考虑空值。我更喜欢使用sum( case ... end )技术,因为它使意图明确:任何对SQL的理解不符合鼻烟的人都会发现结果更少......令人惊讶。

希望这有帮助。