SQL计数项目状态历史记录在日期范围内的项目项

时间:2014-04-10 01:14:19

标签: sql database postgresql

我有4张桌子:

projects: id, title, current_status_id
statuses: id, label
status_history: project_id, status_id, created_at
messages: id, project_id, body, created_at

当在应用程序中,项目更改状态(例如,从"引导"到"活动"到"完成")时,将插入status_history行。请注意,created_at列是记录更改日期的时间戳。在状态更改之间,项目中正在发生活动并创建消息。例如,项目初始化为" lead"状态,一些消息是在项目进入这个"领导"州,项目改为"活跃"状态,在项目处于此状态时创建一些消息,依此类推。

我想创建一个查询,显示:日期,"引导"中创建的消息数量。项目,#在"活动"中创建的消息项目和具有其他状态的项目中的#消息。这可以在一个查询中完成吗?我正在使用PostgreSQL。


这是一些伪代码,希望能够阐明我正在寻找的东西。

* Start at the earliest date
* Find all projects whose status was 'lead' on that date
* Count the number of created messages from these projects with that date
* Find all projects whose status was 'active' on that date
* Count the number of created messages from these projects with that date
* Find all projects whose status was anything else on that date
* Count the number of created messages from these projects with that date
* ... some projects change status, some stay the same, business happens ...
* Go to next date
* Find all projects whose status was 'lead' on that date
* Count the number of created messages from these projects with that date
* Find all projects whose status was 'active' on that date
* Count the number of created messages from these projects with that date
* Find all projects whose status was anything else on that date
* Count the number of created messages from these projects with that date
* ... some projects change status, some stay the same, business happens ...
* keep doing this until the present

虽然项目确实有一个current_status_id列,但它是当前状态,不一定是上个月项目的状态。项目的状态不会每天都在变化 - 每个项目都不会每天创建一个status_history行。

3 个答案:

答案 0 :(得分:0)

您正在寻找这样的查询......这是MSSQL但我假设与Postgresql非常相似,或者您可以在线找到正确的语法。

SELECT count(*) AS 'count', messages.created_at, statuses.label
FROM messages
JOIN projects ON projects.id = messages.project_id
JOIN status_history ON projects.id = status_history.project_id
JOIN statuses ON statuses.id ON status_history.status_id
GROUP BY created_at, statues.label

答案 1 :(得分:0)

尝试以下内容。

将“lead”和“active”替换为这两种状态的状态ID。

请注意,所选的第一个字段是将created_at时间戳转换为日期值(删除时间)。

提供的计数显示了使用这些状态新创建的项目数。它们不包括已经存在但在给定日期更改为这些状态的项目。这是通过not exists子查询完成的。

select      date(created_at) as dt
            , sum(case when sh.status_id = 'lead' then 1 else 0 end) as num_lead
            , sum(case when sh.status_id = 'active' then 1 else 0 end) as num_active
            , sum(case when sh.status_id not in ('lead','active') then 1 else 0 end) as num_else
from        status_history sh
where       not exists
                    (   select  1
                        from    status_history x
                        where   x.project_id = sh.project_id
                            and x.created_at < sh.created_at    )
group by    date(created_at)
order by    1

答案 2 :(得分:0)

怎么样:

SELECT to_char(tmp.date, 'YYYY-MM-DD') as date, COUNT(tmp.status = 'lead') as num_lead,  COUNT(tmp.status = 'active') as num_active FROM 
(
    SELECT m.created_at AS date, COUNT(m.id) as messages, s.label as status FROM messages AS m
    INNER JOIN project AS p ON p.id = m.project_id
    INNER JOIN statuses AS s ON s.id = p.current_status_id
    GROUP BY m.created_at, s.id, s.label
) as tmp
GROUP BY tmp.date;

分组应该是100%正确的(因为它不清楚一个id只属于一个文本表示,标签不是primary_key!)

临时表包含&#34;每个日期的消息和project_status_label&#34;的所有关系。外部选择函数只改变维度。