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;
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