我在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
答案 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
)。