带有Joins和Union All的MySQL SUM查询

时间:2018-03-27 15:52:30

标签: mysql

有人可以告诉我为什么下面的查询中的第二个LEFT JOIN(previous_spend)返回的应该是它应该的两倍吗?

如果我删除了第一个LEFT JOIN,它会返回正确的数量,所以我认为由于第一次LEFT JOIN而导致结果加倍,但我不知道如何重写查询以避免这种情况。

非常感谢任何帮助。

更新:我在这里创建了一个稍微容易理解的版本:这是一个实例:http://sqlfiddle.com/#!9/6a9358/1 - 你可以看到'current_spend'应该返回300英镑。

SELECT 
    COALESCE(SUM(current_spend.total_spend), 0) AS total_spend, 
    COALESCE(SUM(previous_spend.total_previous_spend), 0) AS total_previous_spend, 
    COALESCE(SUM(current_spend.total_spend), 0) - COALESCE(SUM(previous_spend.total_previous_spend), 0) AS total_spend_diff,
    100 * (COALESCE(SUM(current_spend.total_spend), 0) - COALESCE(SUM(previous_spend.total_previous_spend), 0)) / COALESCE(SUM(previous_spend.total_previous_spend), 0) AS total_spend_diff_perc
FROM customer_scheme

LEFT JOIN (
    SELECT SUM(spend_1 + spend_2) AS total_spend, user_id
    FROM customer_spend
    WHERE customer_spend.spend_year = '2017'
    GROUP BY user_id
 UNION ALL
    SELECT SUM(spend_1 + spend_2 + spend_3 + spend_4 + spend_5 + spend_6 + spend_7 + spend_8 + spend_9 + spend_10 + spend_11 + spend_12) AS total_spend, user_id
    FROM customer_spend
    WHERE customer_spend.spend_year = '2018'
    GROUP BY user_id
 UNION ALL
    SELECT SUM(spend_1 + spend_2 + spend_3 + spend_4 + spend_5 + spend_6 + spend_7 + spend_8 + spend_9 + spend_10 + spend_11 + spend_12) AS total_spend, user_id
    FROM customer_spend
    WHERE customer_spend.spend_year = '2019'
    GROUP BY user_id
 UNION ALL
    SELECT SUM(spend_1 + spend_2) AS total_spend, user_id
    FROM customer_spend
    WHERE customer_spend.spend_year = '2020'
    GROUP BY user_id
) as current_spend
    ON current_spend.user_id = customer_scheme.user_id

LEFT JOIN
(
    SELECT SUM(spend_1 + spend_2) AS total_previous_spend, user_id
    FROM customer_spend
    WHERE customer_spend.spend_year = '2013'
    GROUP BY user_id
 UNION ALL
    SELECT SUM(spend_1 + spend_2 + spend_3 + spend_4 + spend_5 + spend_6 + spend_7 + spend_8 + spend_9 + spend_10 + spend_11 + spend_12) AS total_previous_spend, user_id
    FROM customer_spend
    WHERE customer_spend.spend_year = '2014'
    GROUP BY user_id
 UNION ALL
    SELECT SUM(spend_1 + spend_2 + spend_3 + spend_4 + spend_5 + spend_6 + spend_7 + spend_8 + spend_9 + spend_10 + spend_11 + spend_12) AS total_previous_spend, user_id
    FROM customer_spend
    WHERE customer_spend.spend_year = '2015'
    GROUP BY user_id
 UNION ALL
    SELECT SUM(spend_1 + spend_2) AS total_previous_spend, user_id
    FROM customer_spend
    WHERE customer_spend.spend_year = '2016'
    GROUP BY user_id

) as previous_spend
    ON previous_spend.user_id = customer_scheme.user_id

LEFT JOIN user
    ON customer_scheme.user_id = user.user_id

WHERE customer_scheme.scheme_id = 36

AND customer_scheme.customer_scheme_access = 'Yes'
AND user.user_deleted_at IS NULL
AND user_type = 'Customer'
AND user.user_status IN (1)

ORDER BY total_spend_diff DESC

2 个答案:

答案 0 :(得分:0)

您的查询摘要是

(customer_scheme LEFT JOIN current_spend)附加(customer_scheme LEFT JOIN previous_spend)

如果使用current_spend删除LEFT JOIN:

查询将是customer_scheme LEFT JOIN previous_spend

这意味着,对于customer_scheme中的一个用户,2013年的previous_spend将获得一行,2014年将获得一行,2015年将获得一行,2016年将获得一行

在总结时,你将总结上述所有4行。

如果您使用current_spend进行LEFT JOIN:

对于第一次使用current_spend进行LEFT JOIN,您将获得2017年的一行,2018年的一行,2019年的一行和2020年的一行。

因此,对于一个user_id,您将获得4行。现在,您将使用这4行加入previous_spend(如前所述,您将只加入一行)。在总结时,这会产生不同。

如果您可以与一些测试数据共享一个sql小提琴,我会尝试提供更好的见解。

答案 1 :(得分:0)

试试这个:

SELECT 
    SUM(IFNULL(current_spend.total_spend, 0)) AS total_spend, 
    SUM(IFNULL(previous_spend.total_previous_spend, 0)) AS total_previous_spend, 
    SUM(IFNULL(current_spend.total_spend, 0)) - SUM(IFNULL(previous_spend.total_previous_spend, 0)) AS total_spend_diff,
    100 * (SUM(IFNULL(current_spend.total_spend, 0)) - SUM(IFNULL(previous_spend.total_previous_spend, 0))) / SUM(IFNULL(previous_spend.total_previous_spend, 0)) AS total_spend_diff_perc

FROM 

customer_scheme

LEFT JOIN 

(
    SELECT SUM(spend_1 + spend_2 + spend_3 + spend_4 + spend_5 + spend_6 + spend_7 + spend_8 + spend_9 + spend_10 + spend_11 + spend_12) AS total_spend, user_id, customer_spend.spend_year
    FROM customer_spend
    WHERE customer_spend.spend_year in ('2017','2018','2019','2020') 
    GROUP BY user_id, customer_spend.spend_year
) as current_spend

    ON current_spend.user_id = customer_scheme.user_id

INNER JOIN

(
    SELECT SUM(spend_1 + spend_2 + spend_3 + spend_4 + spend_5 + spend_6 + spend_7 + spend_8 + spend_9 + spend_10 + spend_11 + spend_12) AS total_previous_spend, user_id, customer_spend.spend_year
    FROM customer_spend
    WHERE customer_spend.spend_year in ('2013','2014','2015','2016') 
    GROUP BY user_id, customer_spend.spend_year
) as previous_spend

    ON previous_spend.user_id = customer_scheme.user_id

LEFT JOIN user

    ON customer_scheme.user_id = user.user_id

WHERE customer_scheme.scheme_id = 36

AND customer_scheme.customer_scheme_access = 'Yes'
AND user.user_deleted_at IS NULL
AND user_type = 'Customer'
AND user.user_status IN (1)

ORDER BY total_spend_diff DESC;