1

I am using MySql.

I have table job that has a primary key job_pk_id and the table stores details of every job. Also I have a table job_running_status where job table's job_pk_id is a foreign key and this table basically contains records of when a job ran for each job_pk_id.There will be multiple entries for the same job_pk_id as the same job runs multiple times. job_running_status table also has a field job_start_time that gives the start time for each instance of the running of the job.

Now my requirement is to get the latest job_running_status for every job . The latest job_running_status would be chosen based on the latest job_start_time(for that particular job only) value in job_running_status.

I know this can be achieved using INNER JOIN and ORDER BY job_start_time desc between job table and job_running_status table but my challenge is this ORDER BY becomes applicable across all the jobs in the JOIN but I need to be applicable only across records that are corresponding to a particular job.

EDIT I understand it might be confusing to understand me by just reading so I am providing some examples:

job table:

Job Table Image

job_running_status table:

job_running_status image

My final requirement after joining both the tables

My final requirement after joining both the tables

Note: while joining I a should be getting only 1 record corresponding to every JOB table record. This record is chosen based on the latest job_start_time for that JOB.

philipxy
  • 14,867
  • 6
  • 39
  • 83
DockYard
  • 989
  • 2
  • 12
  • 29
  • 3
    Showing some sample data would be nice ^ ^ – Tim Biegeleisen Jul 25 '18 at 06:14
  • 'The latest job_running_status would be chosen based on the latest job_start_time(for that particular job only) value in job_running_status.' You only appear to be selecting 1 record per job so why would you need an order by other than on job? – P.Salmon Jul 25 '18 at 06:22
  • 'but I need to be applicable only across records that are corresponding to a particular job.' - so just put a filter if you have that jobname/id – Aritra Bhattacharya Jul 25 '18 at 06:25
  • Search for correlated sub queries.BTW sample data and expected output is better as text , which we can use rather than images which we can't. – P.Salmon Jul 25 '18 at 07:01
  • @TimBiegeleisen Edited my original post to give example. – DockYard Jul 25 '18 at 07:08
  • @P.Salmon Edited my original post to give example. – DockYard Jul 25 '18 at 07:09
  • @AritraBhattacharya Edited my original post to give example. – DockYard Jul 25 '18 at 07:09
  • Please: Use text, not images/links, for text (including tables). Read & act on [mcve]. Clarify via post edits, not comments. Also, this is faq; it has a tag; always google many clear concise phrasings of your problem/goal/issue/question & read many answers before considering asking. – philipxy Jul 25 '18 at 22:26
  • Possible duplicate of [Select max value of each group](https://stackoverflow.com/questions/4510185/select-max-value-of-each-group) – philipxy Jul 25 '18 at 22:33

2 Answers2

2

An example of a correlated sub query in a where clause

drop table if exists t,t1;
create table t(id int);
create table t1(jid int,dt date);
insert into t values
(1),(2),(3);

insert into t1 values
(1,'2018-01-01'),
(1,'2018-02-01'),
(2,'2018-01-01'),
(3,'2018-01-01'),
(3,'2018-02-01'),
(3,'2018-03-01');

select t.id,t1.dt
from t
join t1 on t1.jid = t.id
where t1.dt =(select max(dt) from t1 where t1.jid = t.id);

+------+------------+
| id   | dt         |
+------+------------+
|    1 | 2018-02-01 |
|    2 | 2018-01-01 |
|    3 | 2018-03-01 |
+------+------------+
3 rows in set (0.00 sec)

If you need the latest n records and you are not on version 8.0 or higher you can use row number simulation

select t.id,s.dt
from t
join 
(select t1.jid,t1.dt ,
          if(t1.jid<>@p,@rn:=1,@rn:=@rn+1) rn,
          @p:=t1.jid p
from t1 
cross join (select @rn:=0,@p:=0) r
order by t1.jid ,t1.dt desc
) s on s.jid = t.id
where s.rn <= 2;

+------+------------+
| id   | dt         |
+------+------------+
|    1 | 2018-01-01 |
|    1 | 2018-02-01 |
|    2 | 2018-01-01 |
|    3 | 2018-02-01 |
|    3 | 2018-03-01 |
+------+------------+
P.Salmon
  • 17,104
  • 2
  • 12
  • 19
  • Got it,it was helpful – DockYard Jul 25 '18 at 07:17
  • This query gives the latest record(i.e 1 record). Is there any way to get more than 1 record using the same criteria that is I want to get the latest 2 job running instances for a job record? – DockYard Jul 25 '18 at 07:28
  • That's scope creep. Your question should have been how can I get the latest n records. And no you cannot use this method. I will add code for this shortly. – P.Salmon Jul 25 '18 at 07:33
  • Ooops, sorry mate....sure add the code...I will edit the title on the original post – DockYard Jul 25 '18 at 07:38
  • Er why?The edit I added 2 days ago starting 'If you need the latest n records ...' covers your requirement. – P.Salmon Jul 27 '18 at 10:17
  • I did not get the part in the query where you used symbol like '@'. For eg. "if(t1.jid<>@p,@rn:=1,@rn:=@rn+1) rn, @p:=t1.jid p". Can you give me some keyword to lookup on google so that I can learn use of such syntax – DockYard Jul 29 '18 at 09:01
  • The keyword is row number simulation have a look at this http://www.mysqltutorial.org/mysql-row_number/ – P.Salmon Jul 29 '18 at 09:31
1

You can try this query. CROSS JOIN with subquery, which get MAX(job_running_status)

Then join job and job_running_status tables.

TestDLL

CREATE TABLE JOB(
   job_pk_id int
);

INSERT INTO JOB VALUES (1),(2),(3);


CREATE TABLE job_running_status(
   fk_job_id INT,
   job_running_status DATE
);

INSERT INTO  job_running_status VALUES (1,'2018-01-01');
INSERT INTO  job_running_status VALUES (1,'2018-02-01');
INSERT INTO  job_running_status VALUES (2,'2018-01-03');
INSERT INTO  job_running_status VALUES (2,'2018-01-02');

Query

SELECT DISTINCT 
    j.job_pk_id,
    jrs.fk_job_id,
    t.job_running_status
FROM 
(SELECT MAX(job_running_status) job_running_status FROM job_running_status) t
CROSS JOIN job j 
inner join job_running_status  jrs on j.job_pk_id = jrs.fk_job_id

[Results]:

| job_pk_id | fk_job_id | job_running_status |
|-----------|-----------|--------------------|
|         1 |         1 |         2018-02-01 |
|         2 |         2 |         2018-02-01 |

sqlfiddle

D-Shih
  • 44,943
  • 6
  • 31
  • 51
  • Got it,it was helpful – DockYard Jul 25 '18 at 07:17
  • This query gives the latest record(i.e 1 record). Is there any way to get more than 1 record using the same criteria that is I want to get the latest 2 job running instances for a job record? – DockYard Jul 25 '18 at 07:28
  • Do you want to use `MAX` like this? `SELECT j.job_pk_id, jrs.fk_job_id, MAX(t.job_running_status) job_running_status FROM job j inner join job_running_status jrs on j.job_pk_id = jrs.fk_job_id GROUP BY j.job_pk_id, jrs.fk_job_id` – D-Shih Jul 25 '18 at 07:31
  • Can I have some rectification please: before the `FROM` you have written `job_running_status` which is a table name. Is is intentional or just a typo ? – DockYard Jul 25 '18 at 07:55