我有两张桌子
Name | ID |
--------+---------+
A | 3 |
A | 5 |
B | 1 |
ID | Count |
--------+---------+
1 | 10 |
2 | 50 |
3 | 15 |
6 | 20 |
我想生成一些连接这两个表的ID以及聚合不匹配条目的结果的东西
Name | ID | Count
--------+---------+----------
A | 3 | 15
A | 5 | 0 *//(doesn't exists)*
A | others | 80 *//(10 (ID 1) + 50 (ID 2) + 20 (ID 6))*
B | 1 | 10
B | others | 85 *//(50 (ID 2) + 15 (ID 3) + 20 (ID 6))*
直到现在我可以获得匹配的项目,但无法获得不匹配的聚合。
我觉得在每个ID列表上执行except
并聚合不匹配的ID并不是一个优雅的解决方案。
希望找到更优雅的解决方案。
修改
我忘了提到我正在使用SQL server
。
oracle解决方案在我的场景中没有任何用处,但在Oracle用户的类似场景中也会有所帮助。
答案 0 :(得分:1)
这个怎么样: 获取匹配的项目并使用第二个查询进行联合。 第二个查询将选择名称,“其他”,总和(计数),并将在名称上分组,其中id不在第一个表的ID中(您可以使用子查询检查)。
如果您愿意,我可以输入,您看起来就像知道自己在做什么,只需要了解如何做到这一点。
答案 1 :(得分:1)
在oracle的情况下使用nvl。 sql server ifnull()和mysql isnull(),左右外部联合而不是全外部
select name, id, sum(cnt) from
(
select name, nvl(to_char(a.id), 'others') id, nvl(b.count,0) cnt
from table1 a
full outer join
table2 b on a.id = b.id)
group by name, id
答案 2 :(得分:0)
LINQ解决方案就是:
from n in Names
join c in Counts on n.ID equals c.ID into outer
select new { n.Name,
ID = outer.Count() > 1 ? "others" : n.ID.ToString(),
Sum = ((int?)outer.Sum(x => x.Count)) ?? 0 }
它相当于外部联接,但也有一些技巧可以将null
转换为0
。在linq-to-sql中,这很好地转换为SQL。因为它被翻译成SQL outer.Count()
,所以outer
为null
时不会抛出异常。