不显示当月数据

问题描述 投票:0回答:1
SELECT TO_CHAR(months.month, 'YYYY-MM') AS month,
       COALESCE(SUM(dm.revenue)::FLOAT, 0.0) AS total_amount,
       COALESCE(COUNT(dm.id), 0) AS value,
       array_agg(dm.id) AS lost_deal_ids
FROM (
    SELECT generate_series(DATE_TRUNC('month', CURRENT_DATE) - INTERVAL '4 months', DATE_TRUNC('month', CURRENT_DATE), INTERVAL '1 month')::DATE AS month
) months
LEFT JOIN deal_management dm ON TO_CHAR(dm.closing_date, 'YYYY-MM') = TO_CHAR(months.month, 'YYYY-MM') AND dm.employee_id = 'sojdosdj2920320323'
LEFT JOIN lookup_data ld ON ld.id = dm.pipeline_id
WHERE (TO_CHAR(months.month, 'YYYY-MM') BETWEEN TO_CHAR(CURRENT_DATE - INTERVAL '4 months', 'YYYY-MM') AND TO_CHAR(CURRENT_DATE, 'YYYY-MM')
    OR TO_CHAR(months.month, 'YYYY-MM') = TO_CHAR(CURRENT_DATE, 'YYYY-MM'))
    AND (ld.level_data = 'Lost' OR ld.id IS NULL)
    AND dm.is_evaluate IS NOT TRUE
GROUP BY TO_CHAR(months.month, 'YYYY-MM')
ORDER BY TO_CHAR(months.month, 'YYYY-MM');

enter image description here

我想查看 2024 年 1 月的当月数据 | 0 | {null} 但如果缺失想看到 0

postgresql
1个回答
0
投票

几乎查询的每个方面都需要关注。这可能有效,而且速度更快:

SELECT to_char(m.mon, 'YYYY-MM') AS month
     , coalesce(sum(dm.revenue)::float, 0.0) AS total_amount
     , count(dm.id) AS count_deals
     , coalesce(string_agg(dm.id::text, ', '), '0') AS lost_deal_ids
FROM   generate_series(date_trunc('month', LOCALTIMESTAMP) - interval '4 mon'
                     , date_trunc('month', LOCALTIMESTAMP)
                     , interval '1 month') m(mon)
LEFT   JOIN deal_management dm ON dm.closing_date >= m.mon
                              AND dm.closing_date <  m.mon + interval '1 mon'
                              AND dm.employee_id = 'sojdosdj2920320323'
                              AND dm.is_evaluate IS NOT TRUE
LEFT   JOIN lookup_data     ld ON ld.id = dm.pipeline_id
                              AND ld.level_data = 'Lost'
GROUP  BY m.mon
ORDER  BY m.mon;

在我们删除对

generate_series()
的无用强制转换后,表函数
FROM
可以在
date
列表中独立存在。

使用

LOCALTIMESTAMP
而不是
CURRENT_DATE
。这样,
date_trunc()
会生成
timestamp
而不是
timestamptz
。参见:

说白了,你的

WHERE
条件都没有任何意义。

  • 这是 100% 多余的。实际上是多余的两次。第一个布尔表达式始终为 true,第二个布尔表达式由第一个布尔表达式暗示:

      WHERE (to_char(months.month, 'YYYY-MM') BETWEEN to_char(CURRENT_DATE - INTERVAL '4 months', 'YYYY-MM') AND to_char(CURRENT_DATE, 'YYYY-MM')
      OR to_char(months.month, 'YYYY-MM') = to_char(CURRENT_DATE, 'YYYY-MM'))
    
  • 这是一种将

    ld.level_data = 'Lost'
    作为连接条件添加到
    LEFT JOIN
    的笨拙、劣质的方法:

      WHERE (ld.level_data = 'Lost' OR ld.id IS NULL)
    
  • 这与

    LEFT JOIN
    相矛盾。 (我通过将其移至连接条件来解决):

      WHERE  dm.is_evaluate IS NOT TRUE
    

count()
永远不会回来
null
。所以
coalesce(count( ...
永远不会做任何有用的事情。

您的加入条件

ON to_char(dm.closing_date, 'YYYY-MM') = to_char(months.month, 'YYYY-MM')
不必要地昂贵。而且不是saragable

请改用可优化控制表达式

ON dm.closing_date >= m.mon AND dm.closing_date < m.mon + interval '1 mon'

使用时间戳值,而不是使用

to_char()
GROUP BY
中的
ORDER BY
生成的文本。更便宜,而且不易出错。

不要使用非描述性的列别名,例如“value”。

考虑聘请顾问。

© www.soinside.com 2019 - 2024. All rights reserved.