【问题标题】:How can I retrieve rows in a given sequence in Oracle / SQL?如何在 Oracle / SQL 中检索给定序列中的行?
【发布时间】:2012-09-13 23:40:43
【问题描述】:

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

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

我最初做的是:

SELECT * FROM MY_TABLE WHERE MY_PK IN (:my_list)

但是返回行的顺序是随机的,不再与给定键的顺序相对应。有没有办法做到这一点? 我唯一想到的是制作许多 SELECT 语句并将它们与 UNION 连接,但是我的主键列表可能很长,并且包含数百甚至数千个键。我想到的替代方法是在应用程序中重新排序行,但我更喜欢不需要这样做的解决方案。

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    首先,通过联合执行此操作不一定有帮助。 除非您有 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
    

    【讨论】:

      【解决方案2】:

      Oracle 仅保证如果使用显式 ORDER BY 语句排序结果集的顺序。所以你的实际问题是,“我如何保证将我的结果按任意顺序排序?”

      嗯,简单的答案是你不能。更复杂的答案是您需要将任意顺序与可以排序的索引相关联。

      我假设您将 ID 列表作为字符串获取。 (如果您将它们作为一个数组或类似的类似表格的东西来获得,那么生活会更容易。)所以首先您需要标记您的字符串。在我的示例中,我使用来自this other SO threadsplitter 函数。我将在公共表表达式中使用它来获取一些行,并使用 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
      

      警告:这是未经测试的代码,但原则是合理的。如果确实遇到无法解决的编译或语法错误,请在 cmets 中提供足够的详细信息。

      【讨论】:

      • Oracle, nothing, no RDBMS 我知道将保证结果的顺序,除非提供ORDER BY 语句。 oracle 不能处理主机变量数组吗?这就是我假设他正在使用的(所以不需要拆分,尽管其余的想法是合理的)。
      【解决方案3】:

      保证结果集上的顺序的方法是使用 ORDER BY,所以我要做的是在一个临时表中插入 2 列您的主键和一个您稍后将用于创建 ORDER BY 的 secuencial ID。您的临时表将是:

      PrimaryKey   ID
      -------------------
      17            1
      13            2
      35            3
      2             4
      9             5
      

      之后,只需在 PrimaryKey 列上使用您的表和临时表的连接,并按临时表的 ID 列排序。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-20
        • 1970-01-01
        • 2021-01-29
        • 2013-06-25
        • 1970-01-01
        • 2015-06-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多