我有两张桌子凭证和分类帐 的总帐:
id total_sale cancel_amount date
1 3000 0 2018-01-20
2 3000 0 2018-01-29
3 5000 0 2018-01-30
4 10000 500 2018-01-30
5 2000 100 2018-01-31
6 2000 0 2018-01-31
凭证:
id expenditure date
1 500 2018-01-20
2 800 2018-01-30
3 1000 2018-01-30
4 200 2018-01-31
5 300 2018-01-31
我想要的结果如[2018-01-29到2018-01-31之间的日期]
date total_sale total_expenditure
2018-01-29 3000 0
2018-01-30 15000 1800
2018-01-31 4000 500
请有人帮忙
答案 0 :(得分:0)
对于此类要求,请始终使用维度表。然后,你永远不会因为加入两个不相同的表而感到困惑。
表:
create schema test;
create table date_dim(date date);
insert into date_dim values ('2018-01-20'),
('2018-01-21'),
('2018-01-22'),
('2018-01-23'),
('2018-01-24'),
('2018-01-25'),
('2018-01-26'),
('2018-01-27'),
('2018-01-28'),
('2018-01-29'),
('2018-01-30'),
('2018-01-31');
create table ledger(id int,total_sale int, cancel_amount int, date date);
insert into ledger values
(1,3000,0,'2018-01-20'),
(2,3000,0,'2018-01-29'),
(3,5000,0,'2018-01-30'),
(4,10000,500,'2018-01-30'),
(5,2000,100,'2018-01-31'),
(6,2000,0,'2018-01-31');
create table voucher(id int, expenditure int, date date);
insert into voucher values
(1,500,'2018-01-20'),
(2,800,'2018-01-30'),
(3,1000,'2018-01-30'),
(4,200,'2018-01-31'),
(5,300,'2018-01-31');
SQL脚本(用于解决方案):
select l.date,total_sale,
total_expenditure
from
(select d.date date,sum(total_sale)total_sale
from ledger l right join date_dim d on l.date=d.date
where d.date between '2018-01-29' and '2018-01-31'
group by 1)l
join
(select d.date date,sum(expenditure)total_expenditure
from voucher v right join date_dim d on v.date=d.date
where d.date between '2018-01-29' and '2018-01-31'
group by 1)v
on l.date=v.date
group by 1,2,3;
结果集:
date total_sale total_expenditure
2018-01-29 3000 (null)
2018-01-30 15000 1800
2018-01-31 4000 500
处的解决方案
答案 1 :(得分:0)
您希望将三个不同的聚合呈现为结果集的列。
您需要创建三个子查询并加入它们。
日期:(http://sqlfiddle.com/#!9/666dcb/1/0)
SELECT DISTINCT DATE(date) date FROM Ledger
UNION
SELECT DISTINCT DATE(date) date FROM Voucher
净销售额:(http://sqlfiddle.com/#!9/666dcb/2/0)
SELECT DATE(date) date,
SUM(total_sale) - SUM(cancel_amount) total_sale
FROM Ledger
GROUP BY DATE(date)
支出:(http://sqlfiddle.com/#!9/666dcb/3/0)
SELECT DATE(date) date,
SUM(expenditure) total_expenditures
FROM Voucher
GROUP BY DATE(date)
然后你需要在约会时加入他们。 (http://sqlfiddle.com/#!9/666dcb/5/0)
SELECT d.date, s.total_sale, e.total_expenditures
FROM (
SELECT DISTINCT DATE(date) date FROM Ledger
UNION
SELECT DISTINCT DATE(date) date FROM Voucher
) d
LEFT JOIN (
SELECT DATE(date) date,
SUM(total_sale) - SUM(cancel_amount) total_sale
FROM Ledger
GROUP BY DATE(date)
) s ON d.date = s.date
LEFT JOIN (
SELECT DATE(date) date,
SUM(expenditure) total_expenditures
FROM Voucher
GROUP BY DATE(date)
) e ON d.date = e.date
WHERE d.date >= somedate AND d.date <= anotherdate
ORDER BY d.date
为什么第一个子查询 - 具有日期的子查询?它确保您在最终结果集中找到没有任何销售或任何支出的日期。
为什么要单独的子查询?因为您希望最终加入三个虚拟表 - 三个子查询 - 每个日期具有零行或一行。如果你连接每个日期有多行的表,你会得到销售和支出的组合爆炸,这将夸大你的总和。
为什么要使用DATE(date)
?因为这样可以使详细信息表中的date
列包含日期/时间值,以备不时之需。
答案 2 :(得分:0)
select l.dates,l.total_sale,
v.total_expenditure
from
(select l.dates dates,sum(total_sale)total_sale
from ledger l
where l.dates between '2018-01-29' and '2018-01-31'
group by l.dates)l
left join
(select v.dates,sum(expenditure)total_expenditure
from voucher v
where v.dates between '2018-01-29' and '2018-01-31'
group by v.dates)v
on l.dates=v.dates;