This answer is only for the explanation of the solutions already presented by @luís-marques and @gordon-linoff.
Since version 11.70 informix has INSTR function that takes a string and looks for a substring, also given, and returns the character position in that string where an occurrence of that substring begins (IBM documentation says it is the end but it is a doc bug).
The solution you are using is:
SELECT
dato1
FROM (
SELECT 4 AS dato1 FROM systables WHERE tabid = 1 UNION
SELECT 2 AS dato1 FROM systables WHERE tabid = 1 UNION
SELECT 1 AS dato1 FROM systables WHERE tabid = 1 UNION
SELECT 3 AS dato1 FROM systables WHERE tabid = 1
)
WHERE dato1 IN (4,2,1,3)
ORDER BY INSTR('4,2,1,3', CAST(dato1 AS VARCHAR(255)));
To get the notion of what are happening you can:
SELECT
dato1,
INSTR('4,2,1,3', CAST(dato1 AS VARCHAR(255))) AS instr_res
FROM (
SELECT 4 AS dato1 FROM systables WHERE tabid = 1 UNION
SELECT 2 AS dato1 FROM systables WHERE tabid = 1 UNION
SELECT 1 AS dato1 FROM systables WHERE tabid = 1 UNION
SELECT 3 AS dato1 FROM systables WHERE tabid = 1
)
WHERE dato1 IN (4,2,1,3)
ORDER BY 2;
That will output:
dato1 instr_res
4 1
2 3
1 5
3 7
But bear in mind that you can have problems using the delimeters, has marked by @gordon-linoff.
For example:
SELECT
dato1,
INSTR('444,44,4', CAST(dato1 AS VARCHAR(255))) AS instr_res
FROM (
SELECT 4 AS dato1 FROM systables WHERE tabid = 1 UNION
SELECT 44 AS dato1 FROM systables WHERE tabid = 1 UNION
SELECT 444 AS dato1 FROM systables WHERE tabid = 1
)
WHERE dato1 IN (444,44,4)
ORDER BY 2;
dato1 instr_res
4 1
44 1
444 1
To get this sorted always delimited the start and end of the values you want, for this case it will be:
SELECT
dato1,
INSTR(',444,44,4,', ','||CAST(dato1 AS VARCHAR(255))||',') AS instr_res
FROM (
SELECT 4 AS dato1 FROM systables WHERE tabid = 1 UNION
SELECT 44 AS dato1 FROM systables WHERE tabid = 1 UNION
SELECT 444 AS dato1 FROM systables WHERE tabid = 1
)
WHERE dato1 IN (444,44,4)
ORDER BY 2;
dato1 instr_res
444 1
44 5
4 8
Another way is using the CHARINDEX function, also available since 11.70. Be aware that the order of the arguments is reverse; first pass the substring to look for and then the source string. The plus side of using CHARINDEX
is that the cast is not required.
SELECT
dato1,
CHARINDEX(','||dato1||',', ',444,4,44,') AS charindex_res
FROM (
SELECT 4 AS dato1 FROM systables WHERE tabid = 1 UNION
SELECT 44 AS dato1 FROM systables WHERE tabid = 1 UNION
SELECT 444 AS dato1 FROM systables WHERE tabid = 1
)
WHERE dato1 IN (444,4,44)
ORDER BY 2;
dato1 charindex_res
444 1
4 5
44 7
When using older versions of Informix that don’t have INSTR
one can use DECODE:
SELECT
dato1
FROM (
SELECT 4 AS dato1 FROM systables WHERE tabid = 1 UNION
SELECT 2 AS dato1 FROM systables WHERE tabid = 1 UNION
SELECT 1 AS dato1 FROM systables WHERE tabid = 1 UNION
SELECT 3 AS dato1 FROM systables WHERE tabid = 1
)
WHERE dato1 IN (4,2,1,3)
ORDER BY DECODE(
dato1,
4, 1,
2, 2,
1, 3,
3, 4
);