2017-07-31 50 views
2

假设我有如下表组通过了空属于所有组

|  a_id | b_id  | price | 
|  1  | 10  | 100 | 
|  1  | 11  | 50  | 
|  1  | NULL  | 300 | 

,我想这组由A_ID和B_ID并得到价格的总和,但NULL拥有属于两个group.I想得到这样的桌子

|  a_id | price | 
|  1  | 400  | 
|  1  | 350  | 

任何想法?提前致谢。

+3

为什么你需要那个?请解释上下文,我认为你可能在第一时间做错了 – Michael

+0

是a_id索引? – AgapwIesu

+0

@AgapwIesu是的,它是主键,但这个表是加入的结果 –

回答

2

你可以使用:

SELECT a_id, 
    SUM(price) + COALESCE(
      (SELECT SUM(price) FROM tab3 WHERE a_id = t.a_id AND b_id IS NULL),0) 
    AS price 
FROM tab3 t 
WHERE b_id IS NOT NULL 
GROUP BY a_id, b_id; 

Rextester Demo

它是如何工作的:

  • 主查询做聚合基于A_ID,B_ID其中B_ID IS NOT NULL
  • 加为b_id的结果值IS NULL(相关的子查询)
+0

在select中执行子查询效率不高。同样的事情可以通过连接来实现,并且效率会更高。无论何时在select中选择一个select,都需要寻找一种方法来执行连接。 – AgapwIesu

+1

取决于数据和索引的数量。有时为了提高效率,mySQL的基于成本的优化器可以做一些有趣的事情。 – xQbert

+1

在这个查询中,子查询将仅对每个不同的'a_id'执行一次,并且可以在性能中击败LEFT JOIN。但是 - 我也会在这里使用COALESCE()来表示没有“组价格”的情况。 –

1

你能做到这一点

select a_id, nonnullsums.sum1 + coalesce(nullbidsums.sum2, 0) from 
(select a_id, sum(price) as sum1 
from mytable 
where b_id is not null 
group by a_id, b_id) as nonnullsums 
left join 
(select a_id, sum(price) as sum2 
from mytable 
where b_id is null 
group by a_id) as nullbidsums 
on nonnullsums.a_id = nullbidsums.a_id 

这是一个单独做了两个和,然后汇总它们。您可以通过为每个a_id添加一个子查询来添加空值的总和,但效率会更低。

+0

如果在基于'a_id'的组中没有对应的NULL值?行将通过'INNER JOIN'跳过。 ** [演示](http://rextester.com/XSXKJT67172)** – lad2025

+0

@ lad2025 - 纠正xQbert的合并想法。 – AgapwIesu

+0

伟大的:)请交换也与GROUP BY线路,它将工作。 – lad2025

3

您可以将数据拆分为两个不同的子集,然后添加。

因此,设置A只包含那些B_ID不为空的记录。 集B只包含那些B_ID为空的记录

这样做的风险是,如果a_ID可能有多个NULL B_ID,那么连接将导致多对多且总和将错误。如果只有1个A_ID,B_ID为空,那么这是有效的。

​​

测试使用lad2025的rextester demo

但是,如果我们有一个A_ID多个NULL B_IDs那么我们就需要以总价之前在子查询的连接。如在此http://rextester.com/PNV55958

SELECT A.a_ID, A.B_ID, sum(A.Price+coalesce(B.Price,0)) price 
FROM tab3 A 
LEFT JOIN (SELECT SUM(Price) Price, A_ID 
      FROM tab3 
      WHERE B_ID is null 
      GROUP BY A_ID) B 
    on A.A_ID = B.A_ID 
WHERE A.B_ID is not null 
GROUP BY A.A_ID, A.B_ID 
+0

'a_id'不明确 – lad2025

+1

Thx!我使用rextester演示更正了它: – xQbert

+0

我认为这会起作用,并且可能是最有效的解决方案。并且很好地抓住了COALESCE。 – AgapwIesu