1

无法让 sql 从 postgresql 数据库进行一些报告。我正在使用两个表,下面列出了相关列:

  • cohead: cohead_id, cohead_number, cohead_orderdate
  • 评论:comment_id、comment_source_id、comment_date、comment_text

两者可以在 cohead_id=comment_source_id 上加入,以查找与订单相关的所有评论。

当我们向我们的订单准备服务提交拣货订单时,我们会通过为相关订单插入带有“已提交”文本的评论来登录。当我们使用订单准备服务关闭订单时,我们会为该订单插入一条“已开票”的注释。

我想做的是获取一个时期内每一天的列表,比如上个月,计算当天或之前提交但截至当天尚未开具发票的订单数量。

我在解决这个问题时遇到了一些概念上的问题,而且我尝试过的连接非常慢。

有任何想法吗?

4

1 回答 1

2

以日期为例'20130731''20130805'例如开始日期和结束日期,此查询将在这两个日期之间的每一天返回您需要的计数。您可以更改实际查询的参数。

;with cte as (
    select d::date as d
    from generate_series('20130731', '20130805', interval '1 day') as d
)
select
    cte.d,
    count(o.cohead_id) as cnt
from cte
    left outer join cohead as o on
        o.cohead_orderdate <= cte.d and
        not exists (
            select *
            from comment as c
            where
                c.comment_date <= cte.d and
                c.comment_text = 'Invoiced' and
                c.comment_source_id = o.cohead_id
        )
group by cte.d
order by cte.d

请参阅SQL FIDDLE 示例- 您可以添加/删除行并检查它是否工作正常。

希望有帮助。

更新:如果您想获取提交日期而不是订单日期,则根本不必查询订单表:

;with cte as (
    select d::date as d
    from generate_series('20130731', '20130805', interval '1 day') as d
), cte2 as (
    select
        c1.comment_date as submitted_date,
        c2.comment_date as invoiced_date,
        count(*) as cnt
    from comment as c1
        left outer join comment as c2 on
           c2.comment_source_id = c1.comment_source_id and
           c2.comment_text = 'Invoiced'
    where c1.comment_text = 'Submitted'
    group by c1.comment_date, c2.comment_date
)
select c1.d, sum(c2.cnt) 
from cte as c1
   left outer join cte2 as c2 on
       c2.submitted_date <= c1.d and
       (c2.invoiced_date is null or c2.invoiced_date > c1.d)
group by c1.d
order by c1.d

请参阅带有更新查询的SQL FIDDLE

更新 2,因为 OP 说他的查询性能有问题,我试图用窗口函数编写另一个。这个想法是获取所有日期的评论数量,其中提交类型的评论减去发票类型的评论,然后获得滚动总数。

;with cte1 as (
    select d::date as d
    from generate_series('20130731', '20130805', interval '1 day') as d
), cte2 as (
    select
        greatest('20130731', c.comment_date) as comment_date,
        c.comment_text, count(*) as cnt
    from comment as c
    where
        c.comment_text in ('Invoiced', 'Submitted') and
        c.comment_date <= '20130805'
    group by greatest('20130731', c.comment_date), c.comment_text
), cte3 as (
    select
        coalesce(cs.cnt, 0) - coalesce(ci.cnt, 0) as cnt,
        coalesce(cs.comment_date, ci.comment_date) as comment_date
    from (select * from cte2 where comment_text = 'Submitted') as cs
        full outer join (select * from cte2 where comment_text = 'Invoiced') as ci on
            cs.comment_date = ci.comment_date
)
select c1.d, sum(c3.cnt) over (order by c1.d)
from cte1 as c1
    left outer join cte3 as c3 on c3.comment_date = c1.d
order by c1.d

SQL 小提琴

于 2013-08-03T17:02:47.647 回答