我有这张表叫做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
由于找不到开票日期列而再次失败
这怎么办?
答案 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
答案 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;
不确定最后一行的逻辑(567892 2018-08-21 200),因为没有数据可以产生该结果。