与总和的MySql Join返回错误的输出

时间:2019-04-29 15:17:15

标签: mysql sql join aggregate

这是我的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在应为6时给出的值为12。 。因此,即使过滤后只有一个记录,它也会对table1.quantity进行两次计数。

请提供正确的SQL查询。

3 个答案:

答案 0 :(得分:1)

我认为问题出在试图在同一计算中两次使用同一张表,而您没有唯一的键。

这是可能的,但是SQL很难看。假设您的“ table3”(未指定)的布局与“ table1”类似,我将采用这种方式:

{{1}}

答案 1 :(得分:1)

我以为您是正确的,唯一的问题是当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

答案 2 :(得分:0)

我没有足够的信息来确定您的模式是否“错误”,这不是您的原始问题。

但是,根据您提供的信息,这就是我要解决的原始问题的方法:

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修改为将来查询中想要的任何值,甚至可能使其成为存储过程,您可以在其中存储to_id作为参数。