2

我有两张桌子

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))*

到目前为止,我可以获得匹配的项目,但无法获得不匹配的聚合。

我觉得except在每个 ID 列表上做一个并聚合不匹配的 ID 并不是一个优雅的解决方案。

想找到一个更优雅的解决问题的方法。

编辑: 我忘了提到我正在使用SQL server. oracle 解决方案在我的场景中没有任何用处,但会在类似的场景中为 Oracle 用户提供帮助。

4

3 回答 3

1

How about this: Get the matched items and do a union with a second query. The second query would select name, 'others', sum(count) and would group on name where id is not in the ids from the first table (you can check that with a subquery).

I can type it out if you want to, you look like you know what you are doing and just need a general idea about how to do it.

于 2013-09-11T07:18:59.637 回答
0

In case of oracle use nvl. sql server ifnull() and mysql isnull() with union of left and right outer instead of full outer

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
于 2013-09-11T07:29:12.157 回答
0

A LINQ solution is this:

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 }

It does the equivalent of an outer join, but also has some trickery to translate a null to 0. In linq-to-sql this nicely translates into SQL. And because it is translated into SQL outer.Count() does not throw an exception when outer is null.

于 2013-09-11T07:35:15.683 回答