sql查询获得两个列之和的差异,这两个列分布在按月分组的两个表中

时间:2018-03-27 03:56:22

标签: sql postgresql

我想编写一个查询来获得两个列之和的差异,这两个列分布在按月分组的两个表中。

架构:

表A

mass numeric,
weight numeric
sampleDt date

表B

mass numeric,
weight numeric,
sampleDt date

表A的示例数据

100|200|2017-01-03
10 |20 |2017-01-05
200|400|2017-12-23

表B的样本数据

10   | 20   | 2017-01-20
10   | 20   | 2017-01-21
100  | 200  | 2017-12-12
2    | 4    | 2017-06-12

预期输出

Month,Year |AMassTotal |AWeightTotal |BMassTotal |BWeightTotal |AMassTotal-BMassTotal

Jan,17 | 110 | 220 | 20 | 40 | 90
Jun,17 | 0   | 0   | 2  | 4  | -2
Dec,17 | 200 | 400 |100 |200 | 100

3 个答案:

答案 0 :(得分:1)

使用完整的外部联接和分组:

select to_char(sampledt, 'yyyy-mm') as month_year,
       coalesce(sum(a.mass),0) as a_mass_total, 
       coalesce(sum(a.weight),0) as a_weight_total, 
       coalesce(sum(b.mass),0) as b_mass_total, 
       coalesce(sum(b.weight),0) as b_weight_total,
       coalesce(sum(a.mass),0) - coalesce(sum(b.mass),0) as mass_total_diff
from table_a a
  full join table_b b using (sampledt)
group by to_char(sampledt, 'yyyy-mm');

如果您希望将年份和月份放在不同的列中,则可以使用:

select extract(year from sampledt) as year, 
       extract(month from sampledt) as month, 
       coalesce(sum(a.mass),0) as a_mass_total, 
       coalesce(sum(a.weight),0) as a_weight_total, 
       coalesce(sum(b.mass),0) as b_mass_total, 
       coalesce(sum(b.weight),0) as b_weight_total,
       coalesce(sum(a.mass),0) - coalesce(sum(b.mass),0) as mass_total_diff
from table_a a
  full join table_b b using (sampledt)
group by extract(year from sampledt), extract(month from sampledt)
order by 1,2;

to_char()函数外,上面是ANSI标准SQL。

在线示例:http://rextester.com/YAN23912

答案 1 :(得分:0)

试试这个:

这适用于 SQL Server

SELECT CONVERT(CHAR(3), sampleDt, 0)+','+CAST(DATEPART(YEAR,sampleDt) AS VARCHAR) [Month,Year]
    ,ISNULL(SUM(CASE WHEN D.Tab=1 THEN mass END),0) AMassTotal 
    ,ISNULL(SUM(CASE WHEN D.Tab=1 THEN weight END),0) AWeightTotal 
    ,ISNULL(SUM(CASE WHEN D.Tab=2 THEN mass END),0) BMassTotal 
    ,ISNULL(SUM(CASE WHEN D.Tab=2 THEN weight END),0) BWeightTotal 
    ,ISNULL(SUM(CASE WHEN D.Tab=1 THEN mass END)-SUM(CASE WHEN D.Tab=2 THEN mass END),0) [AMassTotal-BMassTotal]
FROM(
    SELECT 1 AS Tab,* FROM TableA
    UNION ALL
    SELECT 2,* FROM TableB
    )D
GROUP BY LEFT(DATEPART(MONTH,sampleDt),3)+DATEPART(YEAR,sampleDt)

select CONVERT(CHAR(3), GETDATE(), 0)

SQL小提琴演示:SQL Fiddle Demo

答案 2 :(得分:0)

对于MySQL

SELECT TB.`Month,Year`,
IFNULL(AMassTotal,0),
IFNULL(AWeightTotal,0),
IFNULL(BMassTotal,0),
IFNULL(BWeightTotal,0),
(IFNULL(AMassTotal,0)-IFNULL(BMassTotal,0)) AS 'AMassTotal-BMassTotal' 
FROM
(
SELECT DATE_FORMAT(sampleDt,'%M,%Y') AS `Month,Year`,
SUM(CASE WHEN mass IS NULL THEN 0 ELSE mass END) AS AMassTotal, 
SUM(CASE WHEN weight IS NULL THEN 0 ELSE weight END) AS AWeightTotal
From TableA
GROUP BY DATE_FORMAT(sampleDt,'%M,%Y')
) AS TA
RIGHT JOIN 
(
SELECT DATE_FORMAT(sampleDt,'%M,%Y') AS `Month,Year`,
SUM(CASE WHEN mass IS NULL THEN 0 ELSE mass END) AS BMassTotal, 
SUM(CASE WHEN weight IS NULL THEN 0 ELSE weight END) AS BWeightTotal
FROM TableB
GROUP BY DATE_FORMAT(sampleDt,'%M,%Y')
) AS TB
ON TA.`Month,Year`=TB.`Month,Year`

现场演示

  

http://sqlfiddle.com/#!9/2a6e24/22