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?

Was it helpful?

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top