简体   繁体   中英

Find maximum value for each row

Here is the simplified version of my question. There are two tables one has machines and the second has their info about their state change with date reference(not actualy the date, but the shift index, that's why I have to make another query to get the date itself). I want to get the last state of each machine.
My query is:

SELECT * FROM machines  
LEFT JOIN (SELECT * FROM statechange, dates WHERE....ORDER BY date DESC LIMIT 0,1) AS state
ON state.mid=machines.mid 

But I get only one machine as a result of the query. How can I do it without creating a view?

select m.*,s.`date` from machines as m
inner join (
select mid,`date`
from statechange
order by `date` desc) as s
on m.mid = s.mid
group by m.mid

Assuming that the primary key of the statechange table is something on which Max makes sense (like an integer)

Select ...
From Machines As M
    Left Join   (
                Select S1.mid, Max( S1.PrimaryKeyCol ) As PrimaryKeyCol
                From statechange As S1
                    Join dates As D1
                        On D1.statechangeFK = S1.PrimaryKeyCol
                Where D1.date = (
                                Select Max( D2.date )
                                From dates As D2
                                Where D2.statechangeFK = D1.statechangeFK
                                )
                Group By S1.mid
                ) As LastStateChange
        On LastStateChange.mid = M.mid

    Left Join statechange As S
        On S.PrimaryKeyCol = LastStateChange.PrimaryKeyCol

The last join is in case you want to return columns from the statechange table.


Revision based on additional info

Select ...
From Machines As M
    Left Join   (
                Select S1.mid, Max( S1.PrimaryKeyCol ) As PrimaryKeyCol
                From dates As D1
                    Join statechange As S1
                        On S1.DatesForeignKeyCol = D1.PrimaryKeyCol
                Where D1.date = (
                                Select Max( D2.date )
                                From dates As D2
                                    Join statechange As S2
                                        On S2.DatesForeignKeyCol = D2.PrimaryKeyCol
                                Where S2.mid = S1.mid
                                )
                Group By S1.mid
                ) As LastStateChange
        On LastStateChange.mid = M.mid

    Left Join statechange As S
        On S.PrimaryKeyCol = LastStateChange.PrimaryKeyCol

    Left Join dates As D
        On D.PrimaryKeyCol = S.DatesForeignKeyCol

One of the reasons I used the above approach is to account for the scenario where you might have multiple statechange rows for the same mid and date value. The above approach will use the primary key column as the tie-breaker in that scenario.

You get the latest statechange for every machine by doing something like this.

SELECT mid, max(date)
FROM statechange
GROUP BY mid

Then you join on that to get the current state for every machine. (Guessing at column names.)

SELECT m.*, sc.state, sc.date
FROM machines m
INNER JOIN statechange sc 
    ON ( sc.mid = m.mid )
INNER JOIN (
            SELECT mid, MAX(date) date
            FROM statechange
            GROUP BY mid 
            ) s
    ON ( (s.mid = sc.mid) and (s.date = sc.date) );

I think a view for the current state of every machine might be widely useful, though.

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