如何在Oracle / SQL中检索给定序列中的行?

时间:2012-09-21 14:21:03

标签: sql oracle

我有一个表MY_TABLE,主键为MY_PK。然后,我有一个有序主键列表,例如(17,13,35,2,9)。

现在我想要检索具有这些主键的所有行,并保持行的顺序与给定的键列表相同。

我最初做的是:

SELECT * FROM MY_TABLE WHERE MY_PK IN (:my_list)

但是返回的行的顺序是随机的,并且不再对应于给定键的顺序。有没有办法实现这一目标? 我唯一想到的是制作许多SELECT语句并将它们与UNION连接起来,但我的主键列表可能很长并且包含数百甚至数千个键。我想到的替代方法是在应用程序中对行进行重新排序,但我更倾向于在没有必要的情况下使用解决方案。

3 个答案:

答案 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列排序。