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 || ',', )
【讨论】:
这个指令返回什么? 假设它返回一个数字,表示您要查找的代码字符串中的起始偏移量。因此,当x
是b
时,它会在',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 中的主要内容,如果未能解决你的问题,请参考以下文章
如果在 select 中指定了大写,则 Order by 子句失败
IN() 子句中的 PostgreSQL ORDER BY 值