我有一个表MY_TABLE,主键为MY_PK。然后,我有一个有序主键列表,例如(17,13,35,2,9)。
现在我想要检索具有这些主键的所有行,并保持行的顺序与给定的键列表相同。
我最初做的是:
SELECT * FROM MY_TABLE WHERE MY_PK IN (:my_list)
但是返回的行的顺序是随机的,并且不再对应于给定键的顺序。有没有办法实现这一目标? 我唯一想到的是制作许多SELECT语句并将它们与UNION连接起来,但我的主键列表可能很长并且包含数百甚至数千个键。我想到的替代方法是在应用程序中对行进行重新排序,但我更倾向于在没有必要的情况下使用解决方案。
答案 0 :(得分:2)
首先,用联盟做这件事并不一定有帮助。除非您有order by
子句,否则不保证结果集中行的排序。
这是一个解决方案,虽然它不够优雅:
with keys as (
select 1 as ordering, 17 as pk from dual union all
select 2 as ordering, 13 as pk from dual union all
select 3 as ordering, 35 as pk from dual union all
select 4 as ordering, 2 as pk from dual union all
select 5 as ordering, 9 as pk from dual
)
select mt.*
from My_Table mt join
keys
on mt.my_pk = keys.pk
order by keys.ordering
答案 1 :(得分:2)
如果结果集使用显式ORDER BY语句排序,则 保证结果集的顺序。所以你的实际问题是,“我怎样才能保证将结果分类为任意顺序?”
嗯,简单的答案是你不能。更复杂的答案是您需要将任意顺序与可以排序的索引相关联。
我假设您将ID列表作为字符串。 (如果你把它们作为一个数组或类似的表格生活更容易。)首先,你需要对你的字符串进行标记。在我的示例中,我使用this other SO thread中的splitter
函数。我将在公共表表达式中使用它来获取一些行,并使用rownum伪列来合成索引。然后我们将CTE输出加入到您的表中。
with cte as
( select s.column_value as id
, rownum as sort_order
from table(select splitter('17,13,35,2,9') from dual) s
)
select yt.*
from your_table yt
where yt.id = cte.id
order by cte.sort_order
警告:这是未经测试的代码,但原则是合理的。如果您遇到无法解决的编译或语法错误,请在注释中包含足够的详细信息。
答案 2 :(得分:1)
保证结果集上订单的方法是使用ORDER BY,所以我要做的是插入一个临时表,其中包含2列主键和一个secuencial ID,稍后您将使用它来进行ORDER BY。你的时间表将是:
PrimaryKey ID
-------------------
17 1
13 2
35 3
2 4
9 5
之后只使用您的表和PrimaryKey列上的时态表的连接,并按时间表的ID列排序。