2017-04-03 108 views
0

我试图显示按项目状态过滤的每月所有项目的累计数 - 'raw','finished','lost'。我使用的数据库是PostgreSQL。底部的最新查询与我正在查找的内容接近,但即使该月没有条目,我也想显示每个“状态”的总计数。目前在第3,4和5个月 - 计数为空。会在这里滞后/领导工作吗?或者也许另一种方法。 我试图说明问题尽可能简单。在SQL中递归项目移动

实施例:

id created_at lastmodified closed_at status 
1 2/22/2016 6/21/2016      Raw 
2 2/4/2016 6/21/2016      Raw 
3 8/21/2016 8/26/2016      Raw 
4 8/12/2016 8/26/2016      Raw 
5 2/8/2016 6/21/2016      Raw 
6 8/2/2016 8/26/2016      Raw 
7 6/14/2016 6/29/2016 6/23/2016  Finished 
8 2/12/2016 6/21/2016      Raw 
9 8/18/2016 8/26/2016      Raw 
10 8/8/2016 8/26/2016 8/26/2016  Finished 
11 8/26/2016 8/26/2016      Raw 
12 8/5/2016 8/26/2016      Raw 
13 2/30/2016 2/30/2016 2/30/2016  Finished 
14 6/22/2016 7/19/2016 7/27/2016  Finished 
15 8/12/2016 8/28/2016      Raw 
16 9/20/2016 10/16/2016     Raw 
17 2/15/2016 6/11/2016      Raw 
18 2/6/2016 9/24/2016      Lost 

我要显示的条形图通过时间描绘项的移动,每月的基础上,(说从01-16至04-16,在此实例中),使得item3也将有一个02-16的原始数据库,但它没有数据库中的条目,但是因为它的上一个已知状态是'原始的'应该被考虑。
我认为需要一个CTE(公共表表达式)来生成一个日期表以消耗给定时间段内的所有日期。

with dates as(
select * from generate_series('2016-01-01'::date, 
    '2017-04-01'::date, 
    '1 day'::interval) 

查询结果应该是什么样子,基本的运行计数的总所有项目如何有每个状态的每个月底。

month/yr  raw  finished  lost 
2/2016   5   1  0 
3/2016   6   0  0 
4/2016   7   0  0 
5/2016   7   0  0 
6/2016   8   2  0 
7/2016   7   3  0 
8/2016   13   4  0 
9/2016   13   0  1 
sum    13   4  1 

有三个阶段 - 原材料,成品,lost.You是正确的假设,raw只能要么create_at或modified_at,而finished - 可以拥有所有三个字段填写created_atmodified_atclosed_at。但是,只有当状态更改为finished时,才会填写closed_at。 Lost商品也只能有created_atmodifieddate。创建时的所有项目默认情况下都会达到raw的状态。 达到状态finished的项目将永远不会获得其他日期条目,但我想显示该状态的项目累计数量。

WITH dates as(
    SELECT * FROM generate_series('2016-02-01'::date, '2016-06-01'::date, 
    '1 month'::interval) 
), 
step AS (
    SELECT a.Id, 
    'Raw' AS Step, 
    a.Created_at AS FDate, 
    b.TDate 
    FROM sales a 
    LEFT JOIN 
    (SELECT 
    a.Id, 
    CASE WHEN a.lastmodified IS NULL THEN now() ELSE a.lastmodified END AS TDate 
    FROM sales a 
    WHERE a.lastmodified IS NOT NULL AND a.Status like 'Raw') b 
    ON a.Id = b.Id 
    WHERE a.created_at IS NOT NULL 

    UNION 
    SELECT a.Id, 
    'Lost' AS Step, 
    a.lastmodified AS FDate, 
    b.TDate 
    FROM sales a 
    LEFT JOIN 
    (SELECT a.Id, 
    CASE WHEN a.lastmodified IS NULL THEN now() ELSE a.lastmodified END AS ToDate 
    FROM sales a 
    WHERE a.closed_at IS NOT NULL AND a.Status like 'Finished') b 
    ON a.Id = b.Id 
    WHERE a.lastmodified IS NOT NULL AND a.Status like 'Lost' 

    UNION 
    SELECT a.Id, 
    'Finished' AS Step, 
    a.closed_at::date AS FDate, 
    now() AS TDate 
    FROM sales a 
    WHERE a.closed_at IS NOT NULL AND a.Status like 'Finished' 
) 
    SELECT DISTINCT to_char(d.generate_series::date, 'YYYY-MM') AS date, s.Step AS Status, 
    COUNT(s.Step) OVER (PARTITION BY s.Step ORDER BY to_char(d.generate_series, 'YYYY-MM')) AS count_id 
    FROM dates d 
    LEFT JOIN step s 
    ON to_char(d.generate_series::date,'YYYY-MM') = to_char(s.FDate::date, 'YYYY-MM') 
    ORDER BY date ASC 

此查询使我非常接近我所寻找的。但是,对于没有创建,修改或关闭项目的月份,我的计数为零。如果没有条目,我想显示上个月的累计数。我怎么做到这一点?会在这里滞后/领导工作吗?

+0

你想查询结果看起来像什么东西?忽略图表,这是完全不同的问题。 –

+0

01-01-2016为什么显示3? –

+0

我投票结束这个问题,因为你没有提供足够的信息来回答它。 –

回答

0

好像

  1. 的一切,是不是finished,是raw
  2. finished只能有closed_at
  3. raw只能有created_atmodified_at
  4. 你要我们承担的东西raw之前的所有时间点created_at
  5. 您希望事情在该时间点完成后显示完成?

请澄清你想要什么。最好显示样本数据和最终结果。

所有的说,我觉得你想要的是类似这样的

SELECT d, CASE WHEN d < stat.min THEN 'raw' ELSE 'finished' END 
FROM (VALUES 
    ('2016-01-01'::date, '2017-04-01'::date) 
) AS t(date_start,date_end) 
CROSS JOIN LATERAL generate_series(date_start, date_end, '1 day') 
    AS gs(d) 
CROSS JOIN (
    SELECT min(closed_at) 
    FROM foo 
    WHERE item_id = 'item3' 
    GROUP BY item_id 
) AS stat; 
+0

感谢您的回答。我更新了查询。 – OAK