如何实现这个mysql组查询

如何实现这个mysql组查询,mysql,group-by,Mysql,Group By,我有两张桌子A和B。 我的目标是列出A中的每一行,同时附上B中“金额”的总和 像这样: SELECT a.name, SUM(b.amount) as amount FROM a LEFT JOIN b ON a.id = b.a_id GROUP BY a.id 在此之前没有问题,但我还需要检查B表的'shop_id'是否与某个值匹配,如果匹配,我希望该行的'amount',而不是所有分组行的总和。我希望这是可以理解的 Table A id name --

我有两张桌子A和B。 我的目标是列出A中的每一行,同时附上B中“金额”的总和

像这样:

SELECT a.name, 
       SUM(b.amount) as amount 
FROM a 
LEFT JOIN b ON a.id = b.a_id 
GROUP BY a.id 
在此之前没有问题,但我还需要检查B表的'shop_id'是否与某个值匹配,如果匹配,我希望该行的'amount',而不是所有分组行的总和。我希望这是可以理解的

Table A  
id     name
----------------
1      john
2      doe
3      smith

Table B
a_id    amount    shop
-----------------------
1         4        1
1         3        2
2         2        2
2         7        3
3         3        3
3         1        2
“车间”为1时的预期结果:

name amount shop --------------------- john 4 1 //no SUM, only the value of amount where shop=1 doe 9 0 //sum(7,2) because shop is not 1 smith 4 0 //sum(3,1) 我想在SUM选择中使用一个if语句,类似于此,但是下面的语句返回的不是所需的groupped行值

SELECT a.name,
       ( CASE
           WHEN b.shop <> 1 THEN Sum(b.amount)
           ELSE b.amount
         end ) AS amount,
       ( CASE
           WHEN b.shop <> 1 THEN 0
           ELSE b.shop
         end ) AS shop
FROM   a
       LEFT JOIN b
              ON a.id = b.a_id
GROUP  BY a.id  

有什么想法吗?有没有一种方法可以把这种情况告诉大家,比如:case shop1 THEN。。。。ELSE GROUP BY a.id???

使用所谓的条件聚合是正确的。以下是一个可以工作的版本:

SELECT
    a.name,
    CASE WHEN MAX(CASE WHEN b.shop = 1 THEN 1 ELSE 0 END) > 0
         THEN SUM(CASE WHEN b.shop = 1 THEN b.amount ELSE 0 END)
         ELSE SUM(b.amount) END AS amount,
    MAX(CASE WHEN b.shop = 1 THEN 1 ELSE 0 END) AS shop
FROM a
LEFT JOIN b
    ON a.id = b.a_id
GROUP BY
    a.name;

使用所谓的条件聚合是正确的。以下是一个可以工作的版本:

SELECT
    a.name,
    CASE WHEN MAX(CASE WHEN b.shop = 1 THEN 1 ELSE 0 END) > 0
         THEN SUM(CASE WHEN b.shop = 1 THEN b.amount ELSE 0 END)
         ELSE SUM(b.amount) END AS amount,
    MAX(CASE WHEN b.shop = 1 THEN 1 ELSE 0 END) AS shop
FROM a
LEFT JOIN b
    ON a.id = b.a_id
GROUP BY
    a.name;
您将需要与表b左联接两次。 第一次联接将允许计算和。 只有当shop=1时,第二个联接才会联接。因此,如果我们由于第二次加入而得到一些非空值,我们会考虑,否则,和 请尝试以下操作:

SELECT 
  a.id, 
  a.name, 
  COALESCE(MAX(b2.amount), SUM(b1.amount)) AS amount, 
  COALESCE(b2.shop, 0) AS shop 
FROM a 
LEFT JOIN b AS b1 ON a.id = b1.a_id 
LEFT JOIN b AS b2 ON a.id = b2.a_id AND b2.shop = 1
GROUP BY a.id, a.name 
结果

您将需要与表b左联接两次。 第一次联接将允许计算和。 只有当shop=1时,第二个联接才会联接。因此,如果我们由于第二次加入而得到一些非空值,我们会考虑,否则,和 请尝试以下操作:

SELECT 
  a.id, 
  a.name, 
  COALESCE(MAX(b2.amount), SUM(b1.amount)) AS amount, 
  COALESCE(b2.shop, 0) AS shop 
FROM a 
LEFT JOIN b AS b1 ON a.id = b1.a_id 
LEFT JOIN b AS b2 ON a.id = b2.a_id AND b2.shop = 1
GROUP BY a.id, a.name 
结果


我正在测试,到目前为止看起来不错。谢谢你的快速回复。您认为Madhur的解决方案会运行得更慢吗?好问题,您可以测试这两个查询。他的答案看起来比我的更干净、更复杂。当shop=1时,你可以用Max代替SUM;否则,如果OP的车间数据重复=1;然后它将计算总和,而不仅仅是其中一个值+1我正在测试,到目前为止看起来不错。谢谢你的快速回复。您认为Madhur的解决方案会运行得更慢吗?好问题,您可以测试这两个查询。他的答案看起来比我的更干净、更复杂。当shop=1时,你可以用Max代替SUM;否则,如果OP的车间数据重复=1;然后它将计算总和,而不仅仅是其中一个值+1这会得到一个更高的投票权,因为它太复杂了,实际上看着它很痛苦。@TimBiegeleisen谢谢;但我怀疑它的效率,因为是双连接。@Ninet9您对这两个查询进行了基准测试吗?结果如何?不,我还没有把数据库填满。但是效率是非常重要的,表A大约有10000行,B大约有50000行,两者都有更多的字段。首先,Tim的解决方案似乎更快,但我将测试这两种方法。@Ninet9请参见:。谢谢:这是一个很好的选择,因为它太复杂了,看着它真的很痛苦。@TimBiegeleisen谢谢;但我怀疑它的效率,因为是双连接。@Ninet9您对这两个查询进行了基准测试吗?结果如何?不,我还没有把数据库填满。但是效率是非常重要的,表A大约有10000行,B大约有50000行,两者都有更多的字段。首先,Tim的解决方案似乎更快,但我将测试这两种方法。@Ninet9请参见:。谢谢: