Как вернуть ноль вместо null из подзапроса, когда условие не выполнено

#mysql #sql

#mysql #sql

Вопрос:

У меня есть следующие данные,

 Id Value Tag
1   200   C
1   300   D
1   100   D
2   300   D
2   100   D
  

Я хочу суммировать значения тегов и вычесть сумму D из суммы C. Приведенное ниже работает нормально, если для идентификатора присутствуют оба тега.

 SELECT
    D.sumOfD - C.sumOfC as value,
FROM (
    SELECT IFNULL(ROUND(SUM(value),2),0) as 'sumOfD',Id
    FROM Reports exp WHERE exp.tag = 'D' 
) as D
JOIN (
    SELECT IFNULL(ROUND(SUM(value),2),0) as 'sumOfC' ,Id
    FROM Reports exp WHERE exp.tag = 'C'
) as  C ON C.Id = D.Id
;
  

Но если тег недоступен для идентификатора, ни один из подзапросов не вернет значение. В приведенном выше примере данных есть только тег D для идентификатора 2, поэтому on C.Id = D.Id условие не выполняется. В этом случае я хочу, чтобы возвращался ноль.

Ожидаемый результат

 Id  Value
1   200 (300 100-200) 
2   400 (300 100-0) -- where 0 is the sum of values for tag C for id 2 which is zero 
  

Как я могу это сделать? Я использую mysql 8.0.17

Комментарии:

1. Укажите также ожидаемый результат.

Ответ №1:

Попробуйте следующее — используя conditional aggregation

 select id, 
sum(case when Tag='D' then value else 0 end)-sum(case when Tag='C' then value else 0 end) as diff
from tablename
group by id
  

Комментарии:

1. Я отредактировал свой вопрос, чтобы включить желаемый результат.

2. @Ayubx, этот ответ должен удовлетворить ваш желаемый результат

Ответ №2:

Использование условной агрегации, предложенной Фахми, — отличная идея, вот запрос:

 SELECT sums.D - sums.C as value
FROM (SELECT SUM(IF(tag = 'C', value, 0)) as C,
             SUM(IF(tag = 'D', value, 0)) as D
      FROM Reports
      GROUP BY id
     ) AS sums
  

Хитрость заключается в использовании GROUP BY предложения в вашем id, чтобы легко суммировать ваши значения, и условной агрегации для обоих тегов, чтобы получить их в отдельных значениях.

Ответ №3:

Я думаю, что самый простой метод:

 select id, 
       sum(case when Tag = 'D' then value
                when Tag = 'C' then - value
                else 0 
           end) as diff
from tablename
group by id