Filter data based on last row mysql
-
23-12-2019 - |
Question
I have this simple table setup see fiddle
CREATE TABLE mytable
(`id` int, `itemid` int);
INSERT INTO mytable
(`id`, `itemid`)
VALUES
(1, 111),
(2, 222),
(3, 333),
(4, 444),
(5, 111),
(6, 222),
(7, 333),
(8, 564),
(9, 111),
(10, 121),
(11, 131),
(12, 111),
(13, 353),
(14, 373);
I want to show what the last itemid was in the row next to the current row itemid. I have done that with the below
SELECT
mt.id,
mt.itemid,
(
select mt2.itemid
from mytable mt2
where mt2.id < mt.id
ORDER BY mt2.id DESC
LIMIT 1
) as lastitemid
FROM mytable mt
ORDER BY id DESC
LIMIT 5
This works as expected returning
ID ITEMID LASTITEMID
14 373 353
13 353 111
12 111 131
11 131 121
10 121 111
However I only want to show rows where the lastitemid = 111 for example.
I have tried doing
SELECT
mt.id,
mt.itemid,
(
select mt2.itemid
from mytable mt2
where mt2.id < mt.id
ORDER BY mt2.id DESC
LIMIT 1
) as lastitemid
FROM mytable mt
WHERE lastitemid = 111
ORDER BY id DESC
LIMIT 5
Which gets Unknown column 'lastitemid' in 'where clause'
I have also tried to add
AND mt2.itemid = 111
To the inner query
This doesn't get any errors but returns 111 for all rows which is not what I want as it is invalid eg for id=12 the lastitemid is 131 but it says 111
ID ITEMID LASTITEMID
14 373 111
13 353 111
12 111 111
11 131 111
10 121 111
With my example data set I should get the below results if I had the query right
ID ITEMID LASTITEMID
13 353 111
10 121 111
6 222 111
2 222 111
How can I achieve this?
Solution
Try this:
SELECT mt.id, mt.itemid,
(SELECT mt2.itemid FROM mytable mt2 WHERE mt2.id < mt.id ORDER BY mt2.id DESC LIMIT 1) AS lastitemid
FROM mytable mt
HAVING lastitemid = 111
ORDER BY id DESC
LIMIT 5
Check the SQL FIDDLE DEMO
OUTPUT
| ID | ITEMID | LASTITEMID |
|----|--------|------------|
| 13 | 353 | 111 |
| 10 | 121 | 111 |
| 6 | 222 | 111 |
| 2 | 222 | 111 |
OTHER TIPS
If the ids are guaranteed to be consecutive, you can do this.
SELECT curr.id, curr.itemid, previous.itemid AS lastitemid
FROM mytable curr JOIN mytable previous ON previous.id = curr.id - 1
WHERE previous.itemid = 111
Otherwise, you'd need something like
SELECT curr.id, curr.itemid, previous.itemid AS lastitemid
FROM mytable curr, mytable previous
WHERE previous.id < curr.id
AND previous.itemid = 111
AND NOT EXISTS (
SELECT 1 FROM mytable interloper
WHERE interloper.id < curr.id
AND previous.id < interloper.id )
You just need to use the current query as a table, and then select from it with your where clause.
SELECT
l.id,
l.itemid
FROM
(
SELECT
mt.id,
mt.itemid,
(
select mt2.itemid
from mytable mt2
where mt2.id < mt.id
ORDER BY mt2.id DESC
LIMIT 1
) as lastitemid
FROM mytable mt
) As l
WHERE l.lastitemid = 111
ORDER BY l.id DESC
LIMIT 5