对两个SQL表进行分组和求和,并替换缺少的值

对两个SQL表进行分组和求和,并替换缺少的值,sql,sqlite,join,group-by,Sql,Sqlite,Join,Group By,我有下表“人员”: 另一个表格“金额”: 其中persons.id对应于amounts.customerid 如何返回一个sql查询,该查询返回1月份每人生成的金额,空customerid的名称为“未知” 如果没有左连接,可以分两步完成。首先加入并聚合已知人员。然后加上未知数 select p.name, sum(a.amount) from amounts a join persons p on a.customerid = p.id where a.month = 'Jan' group b

我有下表“人员”:

另一个表格“金额”:

其中persons.id对应于amounts.customerid

如何返回一个sql查询,该查询返回1月份每人生成的金额,空customerid的名称为“未知”


如果没有左连接,可以分两步完成。首先加入并聚合已知人员。然后加上未知数

select p.name, sum(a.amount)
from amounts a
join persons p on a.customerid = p.id
where a.month = 'Jan'
group by p.name

union all

select 'Unknown', sum(amount)
from amounts
where a.month = 'Jan' and customerid is null

我相信一个左连接和
COALESCE()
会在这里起作用:

SELECT COAELSCE(persons.name, 'Unknown') as personname, sum(amount) sumamount
FROM  amounts
    LEFT OUTER JOIN person ON amounts.customerid = persons.id
GROUP BY COALESCE(persons.name, 'Unknown')
WHERE month = 'Jan';

您的需求可以通过
完全外部联接来解决,但SQLite不支持它。
因此,您可以对表
persons
使用
UNION ALL
来包含id为
null的行,然后是
左连接

select p.name, coalesce(sum(a.value), 0) value 
from (select * from persons union all select null, 'Unknown') p 
left join (select * from amounts where month = 'Jan') a
on (p.id = a.customerid) or (p.id is null and a.customerid is null)
where p.id is not null or a.value is not null
group by p.id, p.name
order by p.name is null, p.name
条件:

where p.id is not null or a.value is not null
确保如果没有
customerid
s且
null
为空,则结果中将不会有名为
'Unknown'
value=0的行
请参阅。
结果:


从技术上讲,您需要的是表之间的完全联接。遗憾的是,SQLite不支持
完全连接

有不同的方法来模拟解决方案。然而,对于这个特殊的情况,我认为使用
左连接
来获取所有的人就足够了。然后
UNION ALL
引入未知:

select p.name, coalesce(sum(a.value), 0) value 
from persons p left join
     amounts a
     on a.customerid = p.id and
        a.month = 'Jan'
group by p.name
union all
select 'Unknown', sum(a.value)
from amounts a
where a.customerid is null;
他是一把小提琴


第一个查询使用
left join
将所有客户(即使是那些没有金额的客户)带入。第二个是“unknown”。

名称和值是糟糕的表名。Persons(或者customers)是更好的表名。此外,value是一个糟糕的列名。什么值?做一个外部连接。group by.edited表格名称。@jarlh我正在尝试在sqlite上使用此示例,其中不支持外部联接。还有其他方法吗?您应该提及/标记您使用的SQL方言。如果是Oracle,这里有一个指针:
select p.name, coalesce(sum(a.value), 0) value 
from (select * from persons union all select null, 'Unknown') p 
left join (select * from amounts where month = 'Jan') a
on (p.id = a.customerid) or (p.id is null and a.customerid is null)
where p.id is not null or a.value is not null
group by p.id, p.name
order by p.name is null, p.name
where p.id is not null or a.value is not null
| name    | value |
| ------- | ----- |
| Adam    | 1700  |
| Nick    | 700   |
| John    | 0     |
| Unknown | 210   |
select p.name, coalesce(sum(a.value), 0) value 
from persons p left join
     amounts a
     on a.customerid = p.id and
        a.month = 'Jan'
group by p.name
union all
select 'Unknown', sum(a.value)
from amounts a
where a.customerid is null;