Skip to content
Advertisement

Fetch Data from ID Range and Store in a separate PHP Array – Complex MySQL Query

I have to do a very unusual Mysql query.

I have 1 Table with 2 listings over currently 5k lines that looks like this:

**Id**     **Color**
  2369       0    
  2370       2    
  2372       0    
  2373       1    
  2374       2    
  2375       2    

And so on its all very basic, but now I have to filter it out in a specific order for example:

**Color**
  2
  0
  1
  2

In this Case the query should give me the Ids 2370 – 2374. These Ids should be saved in a php Array or separate PHP Variables. Array is preferred though.

My Question whats the best way to do this.

For those who might want to claim this Question as a duplicate, I have no idea of how to describe this procedure so I was unable to Google it.

Edit:

Example Order This Can be Anything:

**Color**
1.    2
2.    0
3.    1
4.    2

I want to Filter in which line the the first 2 comes like you see in my first code Block its the line with id 2370 after that the same with the 0

One line is depending on its bottom and top line

If I would change Replace the 0 in my Example with a 2 for example none of the id´s in the first code block would be true

I want to check every line from the first till the latest id if this order pops up

Advertisement

Answer

Disclaimer – A bad way to do this 😀 Consider this maybe only when you have to execute this manually or optimization is not an issue.

From your first example 2370 -> 2372 I took the assumption that your ids might skip some numbers but you would still want to match “the next row”, so firstly I created an ugly sub-table to get the id-pair of 4 consecutive ids

SELECT 
    t1.id as t1_id,
    @sep := '-' as "id/color separator",
    @color_len := 1 as "color value length",

    @t2 := (SELECT CONCAT(id, @sep, color) FROM  tbl WHERE id > t1.id ORDER BY id LIMIT 1) as "second row",
    @t2_sep := LOCATE(@sep, @t2) as "second id length",
    @t2_id := SUBSTRING(@t2, 1, @t2_sep - 1) as t2_id,

    @t3 := (SELECT CONCAT(id, @sep, color) FROM  tbl WHERE id > @t2_id ORDER BY id LIMIT 1) as "third row",
    @t3_sep := LOCATE(@sep, @t3) as "third id length",
    @t3_id := SUBSTRING(@t3, 1, @t3_sep - 1) as t3_id,

    @t4 := (SELECT CONCAT(id, @sep, color) FROM  tbl WHERE id > @t3_id ORDER BY id LIMIT 1) as "forth row",
    @t4_sep := LOCATE(@sep, @t4) as "forth id length",
    @t4_id := SUBSTRING(@t4, 1, @t4_sep - 1) as t4_id, 

    t1.color as t1_color,
    SUBSTRING(@t2, @t2_sep + 1, @color_len) as t2_color,
    SUBSTRING(@t3, @t3_sep + 1, @color_len) as t3_color,
    SUBSTRING(@t4, @t4_sep + 1, @color_len) as t4_color
FROM 
    tbl as t1
WHERE
    t1.color = 2;

and then filtered out only the rows matching the color-ordering you wanted

SELECT
    t.t1_id,
    t.t2_id,
    t.t3_id,
    t.t4_id
FROM
  (
      /* previous query */
  ) as t
WHERE
    t.t2_color = 0
AND
    t.t3_color = 1
AND
    t.t4_color = 2;

Here’s the link to fiddle

Now if you would normalize your ids so they wount skip numbers either on saving/deleting records or rearranging over time, the solution would be simple:

SELECT
    t1.id, 
    t2.id,
    t3.id,
    t4.id
FROM
    tbl as t1
INNER JOIN tbl as t2 ON t2.id = t1.id + 1 AND t2.color = 0
INNER JOIN tbl as t3 ON t3.id = t1.id + 2 AND t3.color = 1
INNER JOIN tbl as t4 ON t4.id = t1.id + 3 AND t4.color = 2
WHERE
    t1.color = 2
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement