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

Posted

技术标签:

【中文标题】ORDER BY 子句“IN()”中指定的值,但在泛型 SQL 和 Informix 中【英文标题】:ORDER BY Values especified in clausule "IN()" BUT in Generics SQL and Informix 【发布时间】:2015-12-18 09:04:57 【问题描述】:

我希望不再重复另一个问题...我找不到解决方案。所有解决方案都适用于 mysql

我想按子句 IN 中的值对我的查询结果进行排序。但在互联网和 *** 中,只需在此处找到“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

我不明白...

【问题讨论】:

【参考方案1】:

此答案仅用于解释@luís-marques和@gordon-linoff已经提出的解决方案。

从 11.70 版开始,informix 具有 INSTR 函数,该函数接受一个字符串并查找一个子字符串(同样给出),并返回该字符串中该子字符串开始出现的字符位置(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
);

【讨论】:

¡ 一切都很好理解!然后我明白 order by 在第二步中起作用。首先,您使用句子 CAST(dato1 AS VARCHAR(255))) 的值获得查询结果和排序。非常感谢!【参考方案2】:

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

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

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

返回:

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

返回:

dato1    position
    4           1
    2           2
    1           3
    3           4

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

【讨论】:

似乎它正在转换为长度为+1并填充空格的CHAR,因此需要适当的转换。 INSTR 函数于 11.70 引入。在此之前,对于这个给出的例子,你可以做一个 ORDER BY DECODE(dato1, 4, 1, 2, 2, 1, 3, 3, 4, 5) 嗨,路易斯。伟大的!但我有一个问题。我不明白在这种情况下这个功能是如何工作的。我在想......如果你有查询,在解决 SELECT 和 WHERE 之后,在应用“order by”之前,这将是:1,2,3,4,现在我们应用“order by”。我想象这种情况:SELECT 1,2,3,4 ORDER BY instr('4,2,1,3', CAST(dato1 AS VARCHAR(255))如果我用笔和纸,我会写这个:SELECT 1,2,3,4 ORDER BY instr('4,2,1,3', '1,3,5,7')我不明白。如果有人向我解释这一点,我将不胜感激。提前致谢! @luís-marques @ricardoHenriques 我喜欢使用 DECODE 功能。 @luís-marques 适用于 IN 值较少的小型案例,它更简单。【参考方案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 || ',', )

【讨论】:

这个指令返回什么? 假设它返回一个数字,表示您要查找的代码字符串中的起始偏移量。因此,当xb 时,它会在',a,b,c,' 中查找',b,' 并返回3。这与',a,'',a,'',c,' 返回的值不同,并且顺序正确,所以有用。假设您有一个 INSTR() 函数。 IDS 12.10 确实有INSTR()。 我只是尝试...但它不起作用。起来,这是查询。谢谢! @Marquake 。 . . IBM 确实记录了 instr() (www-01.ibm.com/support/knowledgecenter/SSGU8G_12.1.0/…)。也许CHARINDEX() 可能有用。

以上是关于ORDER BY 子句“IN()”中指定的值,但在泛型 SQL 和 Informix 中的主要内容,如果未能解决你的问题,请参考以下文章

oracle中group by用法

如果在 select 中指定了大写,则 Order by 子句失败

错误:INSERT语句中的列多于VALUES子句中指定的值

IN() 子句中的 PostgreSQL ORDER BY 值

窗口函数只能出现在 SELECT 或 ORDER BY 子句中--update in cursor

MySQL中Union子句不支持order by的解决方法