MYSQL查询从状态表中获取多个状态

时间:2014-12-01 13:00:17

标签: mysql sql join

我的应用程序中有两个与跟踪作业相关的表(MySQL)。第一个表"工作"系统中记录的每个作业包含一行。这是由作业进度表支持的,该表在每次作业移动到新状态时都会跟踪添加了新行的作业的进度。也可以再次重新打开作业并将其推回到先前的状态。因此,job_progress表可以具有相同作业状态但在不同日期/时间的多个条目。

我希望能够通过jobs_progress表获取特定状态的最大日期来获取作业的当前状态。我也希望每个工作能够获得每个工作进展的日期。但是,我正在通过SQL努力做到这一点,并希望得到一些帮助。请参阅以下SQLFiddle:http://sqlfiddle.com/#!2/8b27f/4

这是我目前所拥有的:

SELECT j.*
     , jp.job_state
     , jp.effective_date
     , jp.user_id
  FROM jobs j
  LEFT
  JOIN jobs_progress jp
    ON jp.job_id = j.id;
+----+-----------+-------------+-----------+-----------------------+-----------+---------------+---------------+---------------------+---------+
| id | agency_id | entity_type | entity_id | job_title             | job_state | system_status | job_state     | effective_date      | user_id |
+----+-----------+-------------+-----------+-----------------------+-----------+---------------+---------------+---------------------+---------+
|  1 |       123 | PROPERTY    |        61 | set of keys to be cut | INVOICED  | ACTIVE        | NEW           | 2014-07-08 12:27:54 |     102 |
|  1 |       123 | PROPERTY    |        61 | set of keys to be cut | INVOICED  | ACTIVE        | APPROVED      | 2014-07-08 12:28:02 |     102 |
|  1 |       123 | PROPERTY    |        61 | set of keys to be cut | INVOICED  | ACTIVE        | ASSIGNED      | 2014-07-08 12:29:02 |     102 |
|  1 |       123 | PROPERTY    |        61 | set of keys to be cut | INVOICED  | ACTIVE        | WORK_COMPLETE | 2014-07-08 12:29:11 |     102 |
|  1 |       123 | PROPERTY    |        61 | set of keys to be cut | INVOICED  | ACTIVE        | INVOICED      | 2014-07-08 12:29:27 |     102 |
|  1 |       123 | PROPERTY    |        61 | set of keys to be cut | INVOICED  | ACTIVE        | ASSIGNED      | 2014-08-21 12:29:02 |     103 |
|  1 |       123 | PROPERTY    |        61 | set of keys to be cut | INVOICED  | ACTIVE        | WORK_COMPLETE | 2014-08-30 12:29:11 |     103 |
|  1 |       123 | PROPERTY    |        61 | set of keys to be cut | INVOICED  | ACTIVE        | INVOICED      | 2014-09-01 12:29:27 |     103 |
+----+-----------+-------------+-----------+-----------------------+-----------+---------------+---------------+---------------------+---------+

这就是我想要的:

+----+-----------+-----------------------+---------------------+--------------------------+--------------------------+--------------------------------+-------------------------+
| id | agency_id | job_title             | raised_date (NEW)   | approved_date (APPROVED) | assigned_date (ASSIGNED) | completed_date (WORK_COMPLETE) | invoiced_date (INVOICED)|
+----+-----------+-----------------------+---------------------+--------------------------+--------------------------+--------------------------------+-------------------------+
|  1 |       123 | set of keys to be cut | 2014-07-08 12:27:54 | 2014-07-08 12:28:02      | 2014-08-21 12:29:02      | 2014-08-30 12:29:11            | 2014-09-01 12:29:27     | 
+----+-----------+-----------------------+---------------------+--------------------------+--------------------------+--------------------------------+-------------------------+

以下是我的尝试:

3 个答案:

答案 0 :(得分:2)

这将显示每个状态的最长日期,因此应该包含您想要的所有内容吗?

select 
  j.id,
  j.agency_id,
  j.entity_type,
  j.entity_id,
  j.job_title,
  j.system_status,
  jp.jobstate2 job_state,
  jp.effectivedate
from jobs j
inner join (select job_id,job_state jobstate2,max(effective_date) effectivedate
            from jobs_progress
            group by job_id,job_state) jp 
           on jp.job_id = j.id
order by effectivedate desc

编辑:继续添加一些要求

看起来像是在PIVOTed输出之后。据我所知,在MySQL中没有一种简单的方法可以做到这一点,但你可以试试这个,这不是很好,但确实产生了你之后的结果:

select 
  j.id,
  j.agency_id,
  j.entity_type,
  j.entity_id,
  j.job_title,
  j.system_status,
  j.job_state,
  jp_new.effectivedate raised_date,
  jp_approved.effectivedate approved_date,
  jp_assigned.effectivedate assigned_date,
  jp_complete.effectivedate complete_date,
  jp_invoiced.effectivedate invoice_date
from jobs j
inner join (select job_id,max(effective_date) effectivedate
            from jobs_progress
            where job_state = 'NEW'
            group by job_id,job_state) jp_new
           on jp_new.job_id = j.id
inner join (select job_id,max(effective_date) effectivedate
            from jobs_progress
            where job_state = 'APPROVED'
            group by job_id,job_state) jp_approved
           on jp_approved.job_id = j.id
inner join (select job_id,max(effective_date) effectivedate
            from jobs_progress
            where job_state = 'ASSIGNED'
            group by job_id,job_state) jp_assigned
           on jp_assigned.job_id = j.id
inner join (select job_id,max(effective_date) effectivedate
            from jobs_progress
            where job_state = 'WORK_COMPLETE'
            group by job_id,job_state) jp_complete
           on jp_complete.job_id = j.id
inner join (select job_id,max(effective_date) effectivedate
            from jobs_progress
            where job_state = 'INVOICED'
            group by job_id,job_state) jp_invoiced
           on jp_invoiced.job_id = j.id

编辑:继续添加一些要求

如果您想展示尚未通过所有阶段的工作,请使用LEFT OUTER JOIN代替INNER JOIN

select 
  j.id,
  j.agency_id,
  j.entity_type,
  j.entity_id,
  j.job_title,
  j.system_status,
  j.job_state,
  jp_new.effectivedate raised_date,
  jp_approved.effectivedate approved_date,
  jp_assigned.effectivedate assigned_date,
  jp_complete.effectivedate complete_date,
  jp_invoiced.effectivedate invoice_date
from jobs j
left outer join (select job_id,max(effective_date) effectivedate
                 from jobs_progress
                 where job_state = 'NEW'
                 group by job_id,job_state) jp_new
                on jp_new.job_id = j.id
left outer join (select job_id,max(effective_date) effectivedate
                 from jobs_progress
                 where job_state = 'APPROVED'
                 group by job_id,job_state) jp_approved
                on jp_approved.job_id = j.id
left outer join (select job_id,max(effective_date) effectivedate
                 from jobs_progress
                 where job_state = 'ASSIGNED'
                 group by job_id,job_state) jp_assigned
                on jp_assigned.job_id = j.id
left outer join (select job_id,max(effective_date) effectivedate
                 from jobs_progress
                 where job_state = 'WORK_COMPLETE'
                 group by job_id,job_state) jp_complete
                on jp_complete.job_id = j.id
left outer join (select job_id,max(effective_date) effectivedate
                 from jobs_progress
                 where job_state = 'INVOICED'
                 group by job_id,job_state) jp_invoiced
                on jp_invoiced.job_id = j.id

答案 1 :(得分:0)

这将为您提供行开票的最后日期。如果您想要所有过渡日期,您希望如何显示?

select jobs.*, LastEntry.effective_date 
from jobs
INNER JOIN (SELECT job_id, MAX(effective_date) AS effective_date FROM jobs_progress WHERE job_state = 'INVOICED' GROUP BY job_id) AS LastEntry ON jobs.id = LastEntry.job_id

这只会显示已开票的作业。如果要包含尚未开票的作业,请在派生表上使用LEFT OUTER JOIN而不是内部联接

答案 2 :(得分:0)

您可以使用最新的effective_date获取作业而无需子查询。当您处理更多数据时,联接将比子查询执行得快。

- >最新工作

SELECT jb.id,
jb_pr1.job_state,
jb_pr1.effective_date
FROM 
jobs jb
INNER JOIN jobs_progress jb_pr1 on jb_pr1.job_id = jb.id
LEFT JOIN jobs_progress jb_pr2
ON (jb_pr1.job_id = jb_pr2.job_id AND jb_pr1.effective_date < jb_pr2.effective_date)
WHERE jb_pr2.effective_date IS NULL;

SQL小提琴链接:http://sqlfiddle.com/#!2/8b27f/41