查询Mysql - 返回0表示两个表中不存在的值

时间:2014-09-26 22:17:43

标签: mysql

我在mysql中遇到一个问题。 我有2个表:表A和表B

表A:

名称 - 总计

法国| 20个
西班牙| 10个
英格兰| 5
意大利| 10个
法国| 5

表B

命名

法国
西班牙
意大利
法国
希腊

我的目标是获得表B中每个值的总变量之和,即:

法国| 25个
西班牙| 10个
意大利| 10个
法国| 5
希腊| 0

我的问题是当表A中的值不存在于表A中时,我不能返回0。

此刻我有这个疑问:

select B.name, SUM(A.total) 
from table A , table B
where A.name = B.name
group by B.name
having count(B.name)>1

2 个答案:

答案 0 :(得分:1)

要从表格 B 中没有匹配行的表 A 返回行,您可以使用“外部”联接操作。

首先,抛弃连接操作的旧式逗号语法,然后使用JOIN关键字。要指定“外部”联接,请在“LEFT”关键字前使用关键字“JOIN”,将驱动表(表格 B ,表格放入想要从JOIN左侧返回所有行。并移动执行两个表之间“匹配”的比较谓词,从WHERE子句到{ {1}}条款。

在示例数据中,我注意到表 ON (例如name)中的“重复”B值,并且您显示的结果集包含这些两行:

'France'

我们可以看到如何生成第一行,表 France | 25 France | 5 中两个'France'行的值的总和,但第二行,这有点一个泡菜弄清楚。 (也许这就是您的查询中的HAVING子句试图处理的内容?)

因此,为简化起见,我将继续前进,假设结果中实际上不需要示例输出中的第二行A

根据示例数据和指定的结果(第二个France行除外),我们可以执行类似的操作,使用内联视图从<获取France 5的明确列表强> name

B

如果表格 SELECT d.name , IFNULL(SUM(a.total),0) AS total FROM ( SELECT b.name FROM B b GROUP BY b.name ) d LEFT JOIN A a ON a.name = d.name GROUP BY d.name 实际上没有B的重复值,而是name代替第二'England'行,结果应包括'France'而不是England | 5 ...

如果我们保证表{strong> France | 5 中的name列是唯一的,我们可以取消内联视图,并执行此操作:

B

上面的查询是返回结果的规范模式,就像你描述的那样,但它不是唯一的模式。还有其他几种形式也会返回相同的结果。

作为不同方法的演示,不使用连接操作的方法:

SELECT b.name
     , IFNULL(SUM(a.total),0) AS total
  FROM B b
  LEFT
  JOIN A a
    ON a.name = b.name
 GROUP BY b.name

此方法的执行效果通常不如SELECT b.name , IFNULL(SELECT SUM(a.total) FROM A a WHERE a.name = b.name) AS total FROM B b 返回的大量行的连接。 (对于小集合,我们没有注意到差异,更大的集合表明性能差异会变得明显。)

答案 1 :(得分:1)

我无法从您的问题中看到您需要COUNT(b.name) > 1的原因。但是,这两条信息都可以恢复:

-- Test data
CREATE TABLE a ( name varchar(20), total integer );
CREATE TABLE b ( name varchar(20) );

INSERT INTO a VALUES ( 'France', 20 ), ( 'Spain', 10 ),
( 'England', 5 ), ( 'Italy', 10 ), ( 'France', 5 );

INSERT INTO b VALUES ( 'France' ), ( 'Spain' ), ( 'Italy' ), ( 'France' ), ( 'Greece' );


    SELECT c.name,
    COALESCE(d.number, 0) AS rows,
    COALESCE(e.total, 0) AS total
FROM 
   ( SELECT DISTINCT name FROM a
     UNION
     SELECT DISTINCT name FROM b
     ) AS c
LEFT JOIN
   (  SELECT name, COUNT(1) AS number FROM b GROUP BY name ) AS d
   ON (c.name = d.name)
LEFT JOIN
   (  SELECT name, SUM(total) AS total FROM a GROUP BY name ) AS e
   ON (c.name = e.name);

非常低效但是它完成了这项工作。如果实际上需要b行数等信息,那么查询可能会大大简化。

以上结果是,

name    rows   total
France  2       25
Spain   1       10
England 0        5
Italy   1       10
Greece  1        0

请注意,“行”是指b表的行。所以你可以有0行,就像英格兰的情况一样。如果条件是一个或多个(在您指定的问题中&gt; 1,那么两个或更多<),那么加入表会更容易/ em>的)。

简单地

  

我的目标是获得表B中每个值的总变量之和

您可以先从B中选择唯一的国家/地区名称,然后根据表格A的总数选择LEFT JOIN。要解决丢失国家/地区的NULL值,请使用COALESCE

SELECT c.name, COALESCE(d.total, 0) AS total
FROM 
   ( SELECT DISTINCT name FROM b ) AS c
LEFT JOIN
   ( SELECT name, SUM(total) AS total FROM a GROUP BY name ) AS d
ON (c.name = d.name)

France  25
Spain   10
Italy   10
Greece  0

或者:

SELECT c.name, SUM(COALESCE(a.total, 0)) AS total
FROM 
   ( SELECT DISTINCT name FROM b ) AS c
LEFT JOIN
   a 
ON (c.name = a.name)
GROUP BY c.name

如果您可以在B中使用唯一的国家/地区名称,则可以将( SELECT DISTINCT name FROM b ) AS c替换为b(当然,查询中的c也会变为b )。