简体   繁体   中英

How do I select records where a value has not been exceeded

I wish to extract from a database a list of job Ids where the status for each job has not exceeded a given criteria.

For this example table I want to display all the jobid that have not exceeded status 200 and display only the latest status.

Job-Progress table

Jobid Status Date      Time
1234  100    20131001  080000
1234  200    20131001  100000
1234  300    20131001  140000
9876  100    20131014  110000
5555  100    20131015  100000
5555  200    20131016  080000

The result i am looking for is

Jobid Status Date      Time
9876  100    20131014  110000
5555  200    20131016  080000

Database is on AS400

This is a good use of window/analytic functions.

You can use row_number() to get the most recent status. You can use sum() over to count the number of times that status exceeds 200.

select jobid, Status, Date, Time
from (select jp.*,
             row_number() over (partition by jobid order by date desc, time desc) as seqnum,
             sum(case when status >= 200 then 1 else 0 end) over (partition by jobid) as status_200
      from JobProgress jp
     ) jp
where status_200 = 0 and seqnum = 1;

The where clause then filters to the rows you are looking for.

select t1.* 
from your_table t1
inner join 
(
  select Jobid, max(date*1000000+time) as maxdt
  from your_table
  group by jobid
  having sum(case when status > 200 then 1 else 0 end) = 0
) t2 on t1.jobid = t2.jobid 
     and t1.date*100000+t1.time = maxdt

In SQL server you can use ROW_NUMBER :

SELECT *
FROM (SELECT
            Jobid,
            status,
            ROW_NUMBER() OVER(PARTITION BY Jobid ORDER BY Date DESC) AS rn
      FROM
            Job-Progress
      WHERE Status < 200) A
WHERE RowNum = 1

This is the simplest approach I can think of:

SELECT t.* FROM t
INNER JOIN (
  SELECT jobid, max(date) date FROM t
  GROUP BY jobid
  HAVING COUNT(CASE WHEN status > 200 THEN 1 END) = 0
) s
ON t.jobid = s.jobid AND t.date = s.date

Fiddle here .

A common table expression will allow you to employ the ROW_NUMBER() function to mark the latest row of each job as 1. Then all you need to do is pick that row whenever its status is acceptable.

With x as
(SELECT *,
        ROW_NUMBER() OVER(PARTITION BY Jobid ORDER BY Date, time DESC) AS pick
      FROM JobProgress
)
SELECT jobid, status, date, time
  FROM x
  WHERE Status <= 200
    And pick = 1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM