SQL: простой запрос суммирования с объединением двух других таблиц - PullRequest
1 голос
/ 22 апреля 2019

У меня есть 3 таблицы в sqlite следующим образом:

Таблица 1

ID | x
1, 2.0
2, 3.0
3, 4.0
4, 3.0

Таблица 2

join_ID | x
1, 5.0
1, 6.0
2, 5.0
2, 2.0
3, 2.0
4, 2.0

Таблица 3

join_ID | x
4, 5.0
1, 6.0
3, 5.0
2, 2.0
2, 2.0
1, 2.0

Я хотел бы получить следующую таблицу:

ID | x | x_agg
1, 2, 21
2, 3, 14
3, 4, 11
4, 3, 10

Где x представляет сумму всех строк, содержащих совпадающие идентификаторы. По сути, это то вычисление, которого я хотел бы достичь:

row1 -> 2 + 5 + 6 + 6 + 2 = 21

row2 -> 3 + 5 + 2 + 2 + 2 = 14

row3 -> 4 + 2 + 5 = 11

row4 -> 3 + 2 + 5 = 10

Я использую sqlite в DBManager в QGIS (через пространственный). Выше приведен ограниченный рабочий пример, который я придумал, но он должен повторять условия, в которых я работаю Я придумал следующий код:

 select
  table1.ID,
  ifnull(table1.x,0) as x,
  SUM(ifnull(table2.x,0)) +SUM(ifnull(table3.x,0))+ifnull(table1.x,0) as x_agg
from
 table1
  left join table2 on table1.ID = table2.join_ID
  left join table3 on table1.ID = table3.join_ID
group by
  ID;

Но вместо этого получите:

ID  x   x_agg
1   2.0 40.0
2   3.0 25.0
3   4.0 11.0
4   3.0 10.0

Когда я запускаю выше. Что я здесь не так делаю?

Ответы [ 2 ]

2 голосов
/ 22 апреля 2019

Вероятно, самый простой способ для продолжения здесь - просто объединить два отдельных подзапроса, которые агрегируют вторую и третью таблицы отдельно:

SELECT
    t1.ID,
    t1.x,
    COALESCE(t2.sum_x, 0) + COALESCE(t3.sum_x, 0) AS x_agg
FROM table1 t1
LEFT JOIN
(
    SELECT join_ID, SUM(x) AS sum_x
    FROM table2
    GROUP BY join_ID
) t2
    ON t1.ID = t2.join_ID
LEFT JOIN
(
    SELECT join_ID, SUM(x) AS sum_x
    FROM table3
    GROUP BY join_ID
) t3
    ON t1.ID = t3.join_ID;

Обратите внимание, что я использую левые соединения в обоих местах, потому что может быть, что данный ID из первой таблицы не появится ни в одной из двух других таблиц. В этом случае эффективная сумма должна рассматриваться как ноль.

1 голос
/ 22 апреля 2019

А как насчет этой, которая добавляет суммы таблиц в строковую часть внешнего SELECT без каких-либо объединений?

SELECT id
     , ifnull(x, 0) as x
     , ifnull(x, 0)
         + (SELECT total(x) FROM table2 AS t2 WHERE t1.id = t2.join_id)
         + (SELECT total(x) FROM table3 AS t3 WHERE t1.id = t3.join_id) AS x_agg
FROM table1 AS t1
ORDER BY id;
id          x           x_agg     
----------  ----------  ----------
1           2           21.0      
2           3           14.0      
3           4           11.0      
4           3           10.0      
  • sum() против total(): оба возвращают сумму всех ненулевых значений, но sum() возвращает ноль, а total() возвращает 0,0 для случая, когда каждое значение равно нулю.

Использование следующих данных (обратите внимание на использование индексов для улучшения коррелированных подзапросов):

CREATE TABLE table1(id INTEGER PRIMARY KEY, x NUMERIC);
INSERT INTO table1 VALUES(1,2);
INSERT INTO table1 VALUES(2,3);
INSERT INTO table1 VALUES(3,4);
INSERT INTO table1 VALUES(4,3);
CREATE TABLE table2(join_id INTEGER, x NUMERIC);
INSERT INTO table2 VALUES(1,5);
INSERT INTO table2 VALUES(1,6);
INSERT INTO table2 VALUES(2,5);
INSERT INTO table2 VALUES(2,2);
INSERT INTO table2 VALUES(3,2);
INSERT INTO table2 VALUES(4,2);
CREATE TABLE table3(join_id INTEGER, x NUMERIC);
INSERT INTO table3 VALUES(4,5);
INSERT INTO table3 VALUES(1,6);
INSERT INTO table3 VALUES(3,5);
INSERT INTO table3 VALUES(2,2);
INSERT INTO table3 VALUES(2,2);
INSERT INTO table3 VALUES(1,2);
CREATE INDEX table2_join_id_idx ON table2(join_id);
CREATE INDEX table3_join_id_idx ON table3(join_id);
...