MySql Join with Sum возвращает неправильный вывод - PullRequest
0 голосов
/ 29 апреля 2019

Это мой sql запрос:

select 
    sum(table1.quantity) as t1q, 
    sum(table1_2.quantity) as t2q, 
    sum(table3.quantity) as t3q, 
    table1.pid as pid
from table1 
    inner join table3 on table1.pid=table3.pid
    inner join table1 table1_2 on table1.pid=table1_2.pid 
where 
    table1.to_id=10 and 
    table3.some_id=10 and 
    table1_2.from_id=10 
group by pid;

Пример данных:

Table1:
quantity, to_id, from_id, pid

6, 10, 999999, 345
4, 888999, 10, 345
3, 888999, 10, 345

Если вы наблюдаете выше sql:

Есть 2 таблицы:

Table1 (same table used twice as table1 and table1_2)
Table3

Я хочу получить из table1.to_id = 10 для расчета t1q и table1 (та же таблица) .from_id = 10 для расчета t2q.

Я получаю правильный вывод в некоторых случаях, но в некоторых случаях t1q дает значение как 12, когда оно должно быть 6. В этом сценарии, потому что после объединений, есть 2 записи table1_2 и только одна запись для table1 , Таким образом, он считает table1.quantity дважды, хотя после фильтрации у него только одна запись.

Можете ли вы предоставить правильный запрос sql.

Ответы [ 3 ]

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

Я предполагаю, что вы правы, что ЕДИНСТВЕННАЯ проблема в том случае, когда объединение на table1_2 вызывает дублирование.

В этом случае сначала объедините эту таблицу, прежде чем присоединять к ней.

select 
    sum(table1.quantity) as t1q, 
    sum(table1_2.quantity) as t2q, 
    sum(table3.quantity) as t3q, 
    table1.pid as pid
from
    table1 
inner join
    table3
        on table1.pid=table3.pid
inner join
(
    SELECT
        pid,
        SUM(quantity) AS quantity
    FROM
        table1
    WHERE
        from_id = 10
    GROUP BY
        pid
) 
    table1_2
        on table1.pid=table1_2.pid 
where 
    table1.to_id=10 and
    table3.some_id=10
group by
    pid

Если ваше предположение является неполным, вам может потребоваться сделать это с каждой таблицей ...

select 
    table1.quantity    as t1q, 
    table1_2.quantity  as t2q, 
    table3.quantity    as t3q, 
    table1.pid         as pid
from
 (
    SELECT
        pid,
        SUM(quantity) AS quantity
    FROM
        table1
    WHERE
        to_id = 10
    GROUP BY
        pid
)
    table1
inner join
(
    SELECT
        pid,
        SUM(quantity) AS quantity
    FROM
        table3
    WHERE
        some_id = 10
    GROUP BY
        pid
)
    table3
        on table1.pid=table3.pid
inner join
(
    SELECT
        pid,
        SUM(quantity) AS quantity
    FROM
        table1
    WHERE
        from_id = 10
    GROUP BY
        pid
) 
    table1_2
        on table1.pid=table1_2.pid

Без и с примером набора данных для проверки, есть много предположений.

Но, как правило, агрегируйте перед объединением, если вы присоединяетесь к столбцу, который не уникален в этой таблице.

РЕДАКТИРОВАТЬ: Ответ накомментарий

SELECT
    COALESCE(table1.t1q, 0)           AS t1q,
    COALESCE(table1.t2q, 0)           AS t2q,
    COALESCE(table3.t3q, 0)           AS t3q,
    COALESCE(table1.pid, table3.pid)  AS pid
FROM
(
    SELECT
        pid,
        SUM(CASE WHEN   to_id = 10 THEN quantity ELSE 0 END) AS t1q,
        SUM(CASE WHEN from_id = 10 THEN quantity ELSE 0 END) AS t2q
    FROM
        table1
    WHERE
            to_id   = 10
        OR  from_id = 10
    GROUP BY
        pid
)
    table1
FULL OUTER JOIN
(
    SELECT
        pid,
        SUM(quantity) AS quantity
    FROM
        table3
    WHERE
        some_id = 10
    GROUP BY
        pid
)
    table3
        ON table1.pid = table3.pid

Или ...

SELECT
    SUM(t1q)   AS t1q,
    SUM(t2q)   AS t2q,
    SUM(t3q)   AS t3q,
    pid
FROM
(
    SELECT pid, quantity AS t1q, 0 AS t2q, 0 AS t3q FROM table1 WHERE to_id = 10
    UNION ALL
    SELECT pid, 0              , quantity, 0        FROM table1 WHERE from_id = 10
    UNION ALL
    SELECT pid, 0              , 0       , quantity FROM table3 WHERE some_id = 10
)
    combined
GROUP BY
    pid
1 голос
/ 29 апреля 2019

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

Это возможно, но SQL уродлив.То, как я подошел бы к этому, было бы так, предполагая, что ваша таблица 3 (которую вы не указываете) выложена аналогично вашей таблице 1.

SELECT a.pid,
       b.t1q,
       c.t2q,
       d.t3q
 FROM (SELECT DISTINCT(pid) FROM table1 AS pid) a
 JOIN (SELECT pid, SUM(quantity) AS t1q FROM table1 WHERE to_id = 10 GROUP BY pid) b ON a.pid = b.pid
 JOIN (SELECT pid, SUM(quantity) AS t2q FROM table1 WHERE from_id = 10 GROUP BY pid) c ON a.pid = b.pid
 JOIN (SELECT pid, SUM(quantity) AS t3q FROM table3 WHERE some_id = 10 GROUP BY pid) d ON a.pid = d.pid
0 голосов
/ 29 апреля 2019

У меня недостаточно информации, чтобы определить, является ли ваша схема «неправильной», и это не был ваш первоначальный вопрос.

Однако, учитывая предоставленную вами информацию, я бы так и поступилподход к решению исходного вопроса:

SELECT t1.pid, t1q, t2q, t3q

FROM (SELECT pid, to_id, SUM(quantity) AS t1q FROM table1 GROUP BY pid, to_id) AS t1

INNER JOIN (SELECT pid, from_id, SUM(quantity) AS t2q FROM table1 GROUP BY pid, from_id) AS t2
ON t1.pid = t2.pid AND t1.to_id = t2.from_id

INNER JOIN (SELECT pid, some_id, SUM(quantity) AS t3q FROM table3 GROUP BY pid, some_id) AS t3
ON t1.pid = t3.pid AND t1.to_id = t3.some_id

WHERE t1.to_id = 10

Затем вы можете обновить t1.to_id = 10 до любого значения, которое вы захотите в будущих запросах, и оно может даже стать хранимой процедурой, которую вы передаете в * 1007.* в качестве аргумента.

...