внутреннее объединение нескольких таблиц с использованием одного столбца, оказывающего эффект «множителя» на значения результата - PullRequest
0 голосов
/ 14 декабря 2018

Попытка выполнить простой запрос внутреннего объединения на 4 таблицы (проекты, задачи, расходы и пожертвования).Соединения, кажется, где-то запутываются.Например, SUM (tasks.budget_amount) должен дать комбинированное значение 3 211 385,21, но вместо этого я получаю 49 659 564,60

SELECT projects.id, projects.name, SUM(tasks.budget_amount) as budget, SUM(spendings.amount_spent) AS spending, SUM(donations.donation_amount) AS donation 
    FROM (((projects
    INNER JOIN tasks on tasks.project_id=projects.id)
    INNER JOIN spendings on spendings.task_id=tasks.id)
    INNER JOIN donations on donations.task_id=tasks.id)
    GROUP BY projects.id

Есть ли способ предотвратить это?

1 Ответ

0 голосов
/ 14 декабря 2018

Удалите статистические выражения из списка SELECT (SUM) и удалите GROUP BY, верните первичные ключи / уникальные идентификаторы для каждой таблицы, чтобы увидеть, что происходит.

Что мы увидимявляется полекартовым произведением (или перекрестным произведением), несколько строк из одной таблицы совпадают с несколькими строками из другой таблицы.Спецификация SQL должна возвращать все совпадения.


Один из способов избежать этого - избежать перекрестного продукта, предварительно агрегируя результаты, а затем выполнив объединение.

В качестве примера:

SELECT p.id
     , p.name
     , IFNULL(b.budget,0)    AS budget
     , IFNULL(s.spending,0)  AS spending
     , IFNULL(d.donation,0)  AS donation 
  FROM projects p
  LEFT
  JOIN ( SELECT bt.project_id
              , SUM(bt.budget_amount) AS budget
           FROM tasks bt
         GROUP BY bt.project_id 
       ) b
    ON b.project_id = p.id
  LEFT
  JOIN ( SELECT st.project_id
              , SUM(ss.amount_spent) AS spending
           FROM tasks st
           JOIN spendings ss
             ON ss.task_id = st.id
          GROUP BY st.project_id
       ) s
    ON s.project_id = p.id
  LEFT
  JOIN ( SELECT dt.project_id
              , SUM(dd.donation_amount) AS donation
           FROM tasks dt
           JOIN donations dd
             ON dd.task_id = dt.id
          GROUP BY dt.project_id
       ) d
    ON d.project_id = p.id

Обратите внимание, что каждый из встроенных представлений d, s и b гарантированно возвращает уникальные значения project_id.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...