ORDER BY 在子句 "IN()" 中指定的值,但在泛型 SQL 和 Informix 中

ORDER BY Values especified in clausule "IN()" BUT in Generics SQL and Informix

我希望不会重复另一个问题...我找不到解决方案。所有的解决方案都是针对 MySql.

我想按子句 IN 中的值对查询结果进行排序。但是在 Internet 和 Whosebug 中,只需找到 "MySql" 的解决方案,如下所示:

Order by FIELD in MYSQL

Ordering by specific field value first

MySQL ORDER BY FIELD with %

使用子句 FIELD 或 FIELD_IN_SET。我可以使用类似的东西吗?

谢谢!!


我只是尝试...但它不起作用。这是我的查询。

select * 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', dato1)

这是查询显示:

dato1
1
2
4
3

我不明白...

一种适用于许多数据库的方法是这样的:

where x in ('a', 'b', 'c')
order by instr('a,b,c', x)

当然,分隔符会出问题,所以这样比较安全:

where x in ('a', 'b', 'c')
order by instr(',a,b,c,', ',' || x || ',', )

对于 informix 12.10(开发版),INSTR() 似乎无法将函数参数正确转换为字符类型。

我对 VARCHAR 进行了显式转换,INSTR() 函数开始为 return 正确的值。

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

Returns:

dato1
    4
    2
    1
    3

编辑:

阐明INSTR()函数的使用:

select
    dato1
  , instr('4213', CAST(dato1 AS VARCHAR(255))) AS position
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('4213', CAST(dato1 AS VARCHAR(255)))

Returns:

dato1    position
    4           1
    2           2
    1           3
    3           4

话虽如此,Ricardo 的 DECODE() 建议似乎是更好的选择。

本回答仅对@luís-marques and @gordon-linoff已经给出的解决方案进行说明。

自 11.70 版以来,informix 具有 INSTR 函数,该函数接受一个字符串并查找子字符串,并且 returns 该字符串中该子字符串开始出现的字符位置(IBM 文档说它结束了,但它是一个文档错误)。

您使用的解决方案是:

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

要了解正在发生的事情,您可以:

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;

那将输出:

  dato1   instr_res

      4           1
      2           3
      1           5
      3           7

但请记住,您在使用分隔符时可能会遇到问题,已用 @gordon-linoff 标记。

例如:

    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

为了得到这个排序总是分隔你想要的值的开始和结束,对于这种情况它将是:

    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

另一种方法是使用 CHARINDEX 函数,自 11.70 起也可用。请注意参数的顺序是相反的;首先传递要查找的子字符串,然后传递源字符串。使用 CHARINDEX 的好处是不需要强制转换。

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

当使用没有 INSTR 的旧版本 Informix 时,可以使用 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
);