Группировка и суммирование двух SQL таблиц и замена пропущенных значений - PullRequest
0 голосов
/ 27 марта 2020

У меня есть следующая таблица "персон":

|    id   |  name   | 
| ------  |  -----  |
|    1    |  Adam   |  
|    2    |  Nick   |
|    3    |  John   |

Другая таблица "сумм":

id  amount  month  customerid
 1   500    Jan      1
 2   1000   Feb      1
 3   1200   Jan      1
 4   700    Jan      2
 5   400    Feb      2
 6   210    Jan      null
 7   230    Feb      null

, где Person.id соответствует сумма .customerid

Как мне вернуть sql запрос, который возвращает сумму, сгенерированную на человека в январе, с именем для неопределенного значения «Неизвестно»?

|   name  |  value  | 
| ------  |  -----  |
|   Adam  |  1700   |  
|   Nick  |  700    |
|   John  |  0      |
| Unknown |  210    |

Ответы [ 4 ]

0 голосов
/ 28 марта 2020

Технически, то, что вы хотите - это полное объединение таблиц. К сожалению, SQLite не поддерживает FULL JOIN.

Существуют различные способы эмуляции решения. Для этого конкретного случая, однако, я думаю, что достаточно использовать LEFT JOIN, чтобы получить всех людей. И затем UNION ALL для ввода неизвестных:

select p.name, coalesce(sum(a.value), 0) value 
from persons p left join
     amounts a
     on a.customerid = p.id and
        a.month = 'Jan'
group by p.name
union all
select 'Unknown', sum(a.value)
from amounts a
where a.customerid is null;

Здесь - это дБ <> скрипка.

Первый запрос вводит всех клиентов, используя left join, даже те, у кого нет сумм. Второе приносит в «неизвестность».

0 голосов
/ 27 марта 2020

Я верю, что ЛЕВОЕ СОЕДИНЕНИЕ и COALESCE() сделают трюк здесь:

SELECT COAELSCE(persons.name, 'Unknown') as personname, sum(amount) sumamount
FROM  amounts
    LEFT OUTER JOIN person ON amounts.customerid = persons.id
GROUP BY COALESCE(persons.name, 'Unknown')
WHERE month = 'Jan';
0 голосов
/ 27 марта 2020

Ваше требование может быть решено с помощью FULL OUTER JOIN, но SQLite не поддерживает его. Так что вместо этого вы можете использовать UNION ALL для таблицы persons, чтобы включить строку с идентификатором null и затем LEFT JOIN:

select p.name, coalesce(sum(a.value), 0) value 
from (select * from persons union all select null, 'Unknown') p 
left join (select * from amounts where month = 'Jan') a
on (p.id = a.customerid) or (p.id is null and a.customerid is null)
where p.id is not null or a.value is not null
group by p.id, p.name
order by p.name is null, p.name

Условие:

where p.id is not null or a.value is not null

удостоверяется, что если customerid с null нет, то в результатах не будет строки с именем 'Unknown' с value = 0. Смотрите демо . Результаты:

| name    | value |
| ------- | ----- |
| Adam    | 1700  |
| Nick    | 700   |
| John    | 0     |
| Unknown | 210   |
0 голосов
/ 27 марта 2020

Без левого соединения вы можете сделать это в два этапа. Сначала присоединяйтесь и агрегируйте для известных лиц. Затем добавьте неизвестных.

select p.name, sum(a.amount)
from amounts a
join persons p on a.customerid = p.id
where a.month = 'Jan'
group by p.name

union all

select 'Unknown', sum(amount)
from amounts
where a.month = 'Jan' and customerid is null
...