计算月份之间的总差

Posted

技术标签:

【中文标题】计算月份之间的总差【英文标题】:Calculating grand total difference between months 【发布时间】:2019-12-10 10:45:29 【问题描述】:

我在下面添加了 3 个表格作为示例。我想获得连续几个月之间总计的变化(即一月和二月之间的总计差异)。

下面的查询给了我附加的结果,但我必须为接下来的每个月添加一行新代码。除此之外,它还会为每个总计变体创建一个新列。

opps_id_c:指机会表中的 opps_id contract_id_c:指合约表中的contract_id

如何优化查询? 任何帮助将不胜感激!

表格:发票

+-------------+------------+-----------+---------------+
| issued_date | invoice_id | opps_id_c | contract_id_c |
+-------------+------------+-----------+---------------+
| 1/31/2019   |       6235 |      1235 |          2211 |
| 3/31/2019   |       6235 |      1235 |          2211 |
| 3/31/2019   |       6235 |      1235 |          2211 |
| 1/31/2019   |       6235 |      1235 |          2211 |
| 4/30/2019   |       6235 |      1235 |          2211 |
| 5/31/2019   |       6235 |      1235 |          2211 |
| 6/30/2019   |       6235 |      1235 |          2211 |
| 6/30/2019   |       6235 |      1235 |          2211 |
| 2/28/2019   |       6235 |      1235 |          2211 |
| 2/28/2019   |       6235 |      1235 |          2211 |
+-------------+------------+-----------+---------------+

表格:机会

+---------+-------------+
| opps_id | grand_total |
+---------+-------------+
|    1235 |         460 |
|    1235 |         460 |
|    1235 |         460 |
|    1235 |         460 |
|    1235 |         460 |
|    1235 |         460 |
|    1235 |         460 |
|    1235 |         460 |
|    1235 |         460 |
|    1235 |         460 |
+---------+-------------+

表格:合同

+-------------+-------------+
| contract_id | grand_total |
+-------------+-------------+
|        2211 |         396 |
|        2211 |         396 |
|        2211 |         396 |
|        2211 |         460 |
|        2211 |         460 |
|        2211 |         396 |
|        2211 |         460 |
|        2211 |         169 |
|        2211 |         396 |
|        2211 |         169 |
+-------------+-------------+

我的查询:

SELECT
      SUM(t3.var_jan_feb) AS var_jan_feb,
      SUM(t3.var_feb_mar) AS var_feb_mar,
      SUM(t3.var_mar_apr) AS var_mar_apr,
      SUM(t3.var_apr_may) AS var_apr_may,
      SUM(t3.var_may_jun) AS var_may_jun,
      SUM(t3.var_jun_jul) AS var_jun_jul,
      SUM(t3.var_jul_aug) AS var_jul_aug,
      SUM(t3.var_aug_sept) AS var_aug_sept,
      SUM(t3.var_sept_oct) AS var_sept_oct,
      SUM(t3.var_oct_nov) AS var_oct_nov    
FROM    
(SELECT
    t2.opps_id_c,
    SUM(contract_jan) AS contract_jan,
    CASE WHEN SUM(contract_jan) <> 0 AND SUM(contract_feb) <> 0 THEN SUM(contract_feb) - SUM(contract_jan)
    ELSE 0 END AS var_jan_feb,
    SUM(contract_feb) AS contract_feb,
    CASE WHEN SUM(contract_feb) <> 0 AND SUM(contract_mar) <> 0 THEN SUM(contract_mar) - SUM(contract_feb)
    ELSE 0 END AS var_feb_mar,
    SUM(contract_mar) AS contract_mar,
    CASE WHEN SUM(contract_mar) <> 0 AND SUM(contract_apr) <> 0 THEN SUM(contract_apr) - SUM(contract_mar)
    ELSE 0 END AS var_mar_apr,
    SUM(contract_apr) AS contract_apr,
    CASE WHEN SUM(contract_apr) <> 0 AND SUM(contract_may) <> 0 THEN SUM(contract_may) - SUM(contract_apr)
    ELSE 0 END AS var_apr_may,
    SUM(contract_may) AS contract_may,
    CASE WHEN SUM(contract_may) <> 0 AND SUM(contract_june) <> 0 THEN SUM(contract_june) - SUM(contract_may)
    ELSE 0 END AS var_may_jun,
    SUM(contract_june) AS contract_june,
    CASE WHEN SUM(contract_june) <> 0 AND SUM(contract_july) <> 0 THEN SUM(contract_july) - SUM(contract_june)
    ELSE 0 END AS var_jun_jul,
    SUM(contract_july) AS contract_july,
    CASE WHEN SUM(contract_july) <> 0 AND SUM(contract_aug) <> 0 THEN SUM(contract_aug) - SUM(contract_july)
    ELSE 0 END AS var_jul_aug,
    SUM(contract_aug) AS contract_aug,
    CASE WHEN SUM(contract_aug) <> 0 AND SUM(contract_sept) <> 0 THEN SUM(contract_sept) - SUM(contract_aug)
    ELSE 0 END AS var_aug_sept,
    SUM(contract_sept) AS contract_sept,
    CASE WHEN SUM(contract_sept) <> 0 AND SUM(contract_oct) <> 0 THEN SUM(contract_oct) - SUM(contract_sept)
    ELSE 0 END AS var_sept_oct,
    SUM(contract_oct) AS contract_oct,
    CASE WHEN SUM(contract_oct) <> 0 AND SUM(contract_nov2019) <> 0 THEN SUM(contract_nov) - SUM(contract_oct)
    ELSE 0 END AS var_oct_nov,
    SUM(contract_nov) AS contract_nov        
FROM    
(SELECT  -- grand total contract per month for each opps
    t1.opps_id_c,
    t1.issued_date,
    CASE WHEN t1.issued_date = '2019-01-31' THEN t1.contract_grand_total ELSE 0 END AS contract_jan,
    CASE WHEN t1.issued_date = '2019-02-28' THEN t1.contract_grand_total ELSE 0 END AS contract_feb,
    CASE WHEN t1.issued_date = '2019-03-31' THEN t1.contract_grand_total ELSE 0 END AS contract_mar,
    CASE WHEN t1.issued_date = '2019-04-30' THEN t1.contract_grand_total ELSE 0 END AS contract_apr,
    CASE WHEN t1.issued_date = '2019-05-31' THEN t1.contract_grand_total ELSE 0 END AS contract_may,
    CASE WHEN t1.issued_date = '2019-06-30' THEN t1.contract_grand_total ELSE 0 END AS contract_june,
    CASE WHEN t1.issued_date = '2019-07-31' THEN t1.contract_grand_total ELSE 0 END AS contract_july,
    CASE WHEN t1.issued_date = '2019-08-31' THEN t1.contract_grand_total ELSE 0 END AS contract_aug,
    CASE WHEN t1.issued_date = '2019-09-30' THEN t1.contract_grand_total ELSE 0 END AS contract_sept,
    CASE WHEN t1.issued_date = '2019-10-31' THEN t1.contract_grand_total ELSE 0 END AS contract_oct,
    CASE WHEN t1.issued_date = '2019-11-30' THEN t1.contract_grand_total ELSE 0 END AS contract_nov            
FROM    
(SELECT
    i.invoice_id,
    i.amount,
    i.opps_id_c,
    o.grand_total AS opps_grand_total,
    i.issued_date,
    i.contract_id_c,
    c.grand_total AS contract_grand_total
FROM
    db.invoice i
LEFT JOIN db.opps o ON
    i.opps_id_c = o.opps_id
LEFT JOIN db.contract c ON
    i.contract_id_c = c.contract_id
) AS t1) AS t2    
WHERE 
    (contract_nov > 0
    OR contract_dec > 0
    OR contract_jan > 0
    OR contract_feb > 0
    OR contract_mar > 0
    OR contract_apr > 0
    OR contract_may > 0
    OR contract_june > 0
    OR contract_july > 0
    OR contract_aug > 0
    OR contract_sept > 0
    OR contract_oct > 0
    OR contract_nov2019 > 0)
GROUP BY
    t2.opps_id_c) AS t3

查询结果:

【问题讨论】:

如果您可以最小化您的样本并获取一些更具可读性的数据,那将会更加有用。 @S-Man 我将记录最小化为 10 条,并为两个列名添加了描述。如果可以,请告诉我。 最好采用整数值而不是双精度值,因为如果结果正常,可以更轻松地检查。第二:请将您的随机外观 id 更改为更简单的 A - Z。这将有很大帮助,因为目前很难看到哪些记录应该适合。最后,预期的输出会非常好。 使用postgres解析函数更简单:postgresql.org/docs/9.1/tutorial-window.html @S-Man 由于随着时间的推移,一个 id 在合同中的总数不同,为了简化,我只修改了一个 opps_id 的表。希望应该没问题! 【参考方案1】:
SELECT issued_date,zeroifnull(total-lag(total) OVER (PARTITION BY issued_date ASC)) var
FROM (
    SELECT issued_date, sum(o.grand_total+c.grand_total) total
    FROM Invoice i
    LEFT JOIN Opportunities o
    ON i.opps_id_c=o.opps_id
    LEFT JOIN Contract c
    ON i.contract_id_c=c.contract_id
    GROUP BY 1
 ) t

【讨论】:

以上是关于计算月份之间的总差的主要内容,如果未能解决你的问题,请参考以下文章

将上个月的总金额与当前月份的结果进行比较

JS 计算两个日期之间的月份,不足一个月按一个月计算(求大神指点)

获取两个日期之间的月份 (具体月份)一个是包含头尾 一个不包含头尾

js日期处理函数 -- 判断闰年,获取当月的总天数添加月份

计算postgresql上两个时间戳之间的月份?

sql 计算日期之间的月份