2016-03-15 95 views
0

我遇到以下问题:我应该列印所有国家的沉船数量。所以我写了以下内容:SQL - 使用group by和where显示表中的所有行

use ships; 

select CLASSES.CLASS, COUNT(*) 
from CLASSES 
left join SHIPS on CLASSES.CLASS = SHIPS.CLASS 
left join OUTCOMES on NAME = SHIP 
where RESULT = 'sunk' 
group by CLASSES.CLASS; 

但是如果某个国家没有沉没的船它不会出现在结果中。但是我希望每个国家都能得到结果,如果它没有沉没的船只可以购买0数量。 我该如何做到这一点? 在此先感谢。

+1

呃,你的查询没有任何迹象表明它正在选择一个国家。 –

+0

是的,你是对的!应该用CLASS或反向替换国家(问题不会改变)。 – DPM

回答

1

正确的方式做到这一点是使用LEFT JOIN,但与ON子句中的条件:

select c.CLASS, COUNT(o.RESULT) 
from CLASSES c left join 
    SHIPS s 
    on c.CLASS = s.CLASS left join 
    OUTCOMES o 
    on s.NAME = o.SHIP and 
     o.RESULT = 'sunk' 
group by c.CLASS; 

注意,该表的别名也使查询更容易编写和阅读。

此外,我必须猜测列属于哪些表。当从头开始使用限定的列名时,则没有猜测。

+0

非常感谢! 'left join SHIPS'后你错过了's'。这是最好的和被接受的答案。因此,现在我们在行中没有船的时候有0,因为COUNT(NULL)实际上不会将累加计数加1,对吧? – DPM

+0

@DPM。 。 。正确。 'COUNT(​​)'统计非NULL值。 –

1

这取决于您使用的SQL方言。如果您使用的Informix的数据库,你可以使用NVL()函数:

SELECT <whatever>, nvl(ships, 0) AS ship_num FROM SHIPS; 

使用SQLITE3你可以使用COALESCE()函数:

SELECT <whatever>, coalesce(ships, 0) AS ship_num FROM SHIPS; 

等所有SQL方言将有一个这些功能,但他们都命名不同。但基本原理是相同的 - 如果我得到的值为NULL,则使用提供的值 - 零值,但可以是任何值,甚至列值或字符串“未指定”等。如果提供数据库你正在查询,我可以给你使用的功能。

1

假设无论代码就足够了问题的一个样本中的代码没有提到的每一个地方的国家,有许多方法来算的,我最喜欢的方法是使用if(MySQL的)或case(SQL Server)的内count ..

MySQL的 - 使用if

use ships; 

select CLASSES.CLASS, COUNT(IF(RESULT = 'sunk', 1, NULL)) 
from CLASSES 
left join SHIPS on CLASSES.CLASS = SHIPS.CLASS 
left join OUTCOMES on NAME = SHIP 
group by CLASSES.CLASS; 

SQLSERVER - 使用case

use ships; 

select CLASSES.CLASS, COUNT(CASE WHEN RESULT = 'sunk' THEN 1 ELSE NULL END) 
from CLASSES 
left join SHIPS on CLASSES.CLASS = SHIPS.CLASS 
left join OUTCOMES on NAME = SHIP 
group by CLASSES.CLASS; 
+0

非常感谢!这对我有帮助。你的第一行应该是select CLASSES.CLASS,COUNT(IF(RESULT ='sunk',1,NULL))。 – DPM

+0

对呀,我很想念,谢谢.. – Susilo