将两个表分别合并为WHERE和SUM

时间:2019-09-25 08:51:41

标签: mysql join sum where-clause

我有这张表叫做sales:

vat,    activation
12345   2017-07-28
567892  2018-08-21
224124  2016-08-22

此表称为发票:

cif,   billdate,    amount
12345  2017-07-19   200
12345  2017-07-29   250
12345  2017-08-02   3000
224124 2016-08-24   400
224124 2018-09-08   2499

我想要一张这样的桌子:

vat,   activation, first_month_amount
12345  2017-07-28  450
224124 2016-08-22  400
567892 2018-08-21  200

基本上是在激活当月计费的所有邀请之和。

到目前为止,我已经尝试过:

select * from  sales
LEFT JOIN ( 
    SELECT vat,sum(amount) as first_month_amount
    FROM invoices 
    WHERE month(billdate)=month(activation) 
    Group by cif
    ) as salesdata on sales.vat = salesdata.cif 

查询失败,因为它找不到激活列。

第二次尝试是:

select * from  sales
LEFT JOIN ( 
    SELECT vat,sum(amount) as first_month_amount
    FROM invoices 
    WHERE month(billdate)=month(activation) 
    Group by cif
    ) as salesdata on sales.vat = salesdata.cif 

由于找不到开票日期列而再次失败

这怎么办?

4 个答案:

答案 0 :(得分:0)

一种方法是利用Correlated subquery;另外,仅匹配月份是不够的,您还需要匹配年份,以正确获取“第一个月”金额:

select s.*, 
       (select sum(i.amount) 
        from invoices i 
        where month(i.billdate) = month(s.activation) 
              and year(i.billdate) = year(s.activation) 
              and i.cif = s.vat
       ) first_month_amount
from  sales s 
通过在(cif)表上具有索引invoices,可以使

上面的查询更有效。因此,如果您尚未定义此索引;您可以使用以下命令:

ALTER TABLE invoices ADD INDEX (cif);

但是,此查询的优化程度仍然不够高(至少,按照我的说法)。当前,在日期值上使用Month()Year()函数正在禁止使用billdate表的invoices字段上的索引。

因此,我们可以使查询可更改,如下所示:

select s.*, 
       (select sum(i.amount) 
        from invoices i 
        where i.cif = s.vat 
              and i.billdate 
                    between date_format(s.activation, '%Y-%m-01') 
                            and last_day(s.activation)
       ) first_month_amount
from  sales s 

如果我们在invoices表上定义以下复合索引,则此查询将足够性能。请注意,billdate应该位于索引的末尾,因为它是范围条件:

ALTER TABLE invoices ADD INDEX (cif, billdate);

答案 1 :(得分:0)

此查询将为您提供所需的结果。它按年份和月份cif对销售进行分组,并根据年份和月份的JOIN值创建cif

SELECT s.vat, s.activation, COALESCE(i.amount, 0) AS amount
FROM sales s
LEFT JOIN (SELECT cif, DATE_FORMAT(billdate, '%Y%m') AS billmonth, SUM(amount) AS amount
           FROM invoices
           GROUP BY cif, billmonth) i ON i.cif = s.vat AND i.billmonth = DATE_FORMAT(s.activation, '%Y%m')

输出(请注意vat = 567892的0值,因为invoices中没有数据):

vat     activation  amount
12345   2017-07-28  450
567892  2018-08-21  0
224124  2016-08-22  400

Demo on dbfiddle

答案 2 :(得分:0)

您可以在下面尝试-

select vat, activation,first_month_amount
from sales s
(
SELECT cif,month(billdate) mbill,year(billdate) ybill,sum(amount) as first_month_amount
    FROM invoices 
    Group by cif,month(billdate),year(billdate)
)s1 on s.vat=s1.cif and month(activation)=mbill and year(activation)=ybill

答案 3 :(得分:0)

您可以简单地在表之间进行联接:

select s.vat, s.activation, sum(i.amount)
from sales s
 left join invoices i on last_day(i.billdate)=last_day(s.activation)
group by s.vat, s.activation;

SQLFiddle

不确定最后一行的逻辑(567892 2018-08-21 200),因为没有数据可以产生该结果。

相关问题