【问题标题】:Sort values in an associative array pl/sql对关联数组 pl/sql 中的值进行排序
【发布时间】:2015-04-12 11:52:55
【问题描述】:

如果 ID 是偶数,我必须对对应于该 ID DESC 的值进行排序,如果 ID 是奇数,我必须对值进行 ASC 排序。这是名为 Grades 的表。

   ID|COL1|COL2|COL3|COL4|COL5|COL6|COL7|  
   1 | 6  | 3  | 8  | 4  | 7  | 8  | 4  |  
   2 | 5  | 7  | 9  | 2  | 1  | 7  | 8  |  
   3 | 2  | 7  | 4  | 8  | 1  | 5  | 9  |  
   4 | 8  | 4  | 7  | 9  | 4  | 1  | 4  |  
   5 | 7  | 5  | 2  | 5  | 2  | 6  | 4  |

结果一定是这样的:

  ID|COL1|COL2|COL3|COL4|COL5|COL6|COL7| 
  1 | 3  | 4  | 4  | 6  | 7  | 8  | 8  | 
  2 | 9  | 8  | 7  | 7  | 5  | 2  | 1  | 
  3 | 1  | 2  | 4  | 5  | 7  | 8  | 9  | 
  4 | 9  | 8  | 7  | 4  | 4  | 4  | 1  | 
  5 | 2  | 2  | 4  | 5  | 5  | 6  | 7  |

如您所见,ID=1->奇数,因此值必须按 ASC 排序

这是目前为止的代码:

declare 

type grades_array is table of grades%rowtype index by pls_integer;
grades_a grades_array;
cnt number;


begin 
Select count(id) into cnt from grades;
For i in 1..cnt loop
--I used an associative array 
Select * into grades_a(i) from grades where grades.id=i;
end loop;

For i in grades_a.FIRST..grades_a.LAST loop
if (mod(grades_a(i).id,2)=1)then .......
--I don't know how to sort the specific rows, in this case ASC
--dbms_output.put_line(grades_a(i).col1);
end if;
end loop;
--Also it is specified in the exercise that the table can change, e.g add more columns
end;

【问题讨论】:

  • 提示 1:您可以在 sql 语句中使用 ORDER BY 子句。提示 2:您可以有多个 sql 语句来填充由 IF 检查包围的数组。

标签: sorting plsql oracle11g associative-array


【解决方案1】:

我会简单地使用PIVOT/UNPIVOT

首先对表进行 UNPIVOT 并按升序/降序为每个列值分配一个排名。

SQL Fiddle

查询 1

SELECT id,
       colval,
       ROW_NUMBER () OVER (
          PARTITION BY id
          ORDER BY CASE MOD (id, 2) WHEN 1 THEN colval END,
                   CASE MOD (id, 2) WHEN 0 THEN colval END DESC) r
  FROM x UNPIVOT (colval FOR colname
         IN (col1 AS 'col1', col2 AS 'col2', col3 AS 'col3', col4 AS 'col4',
             col5 AS 'col5', col6 AS 'col6', col7 AS 'col7')
             )

Results

| ID | COLVAL | R |
|----|--------|---|
|  1 |      3 | 1 |
|  1 |      4 | 2 |
|  1 |      4 | 3 |
|  1 |      6 | 4 |
|  1 |      7 | 5 |
|  1 |      8 | 6 |
|  1 |      8 | 7 |
|  2 |      9 | 1 |
|  2 |      8 | 2 |
|  2 |      7 | 3 |
|  2 |      7 | 4 |
|  2 |      5 | 5 |
|  2 |      2 | 6 |
|  2 |      1 | 7 |
|  3 |      1 | 1 |
|  3 |      2 | 2 |
|  3 |      4 | 3 |
|  3 |      5 | 4 |
|  3 |      7 | 5 |
|  3 |      8 | 6 |
|  3 |      9 | 7 |
|  4 |      9 | 1 |
|  4 |      8 | 2 |
|  4 |      7 | 3 |
|  4 |      4 | 4 |
|  4 |      4 | 5 |
|  4 |      4 | 6 |
|  4 |      1 | 7 |
|  5 |      2 | 1 |
|  5 |      2 | 2 |
|  5 |      4 | 3 |
|  5 |      5 | 4 |
|  5 |      5 | 5 |
|  5 |      6 | 6 |
|  5 |      7 | 7 |

然后根据排名PIVOT结果。

查询 2

WITH pivoted AS (
SELECT id,
       colval,
       ROW_NUMBER () OVER (
          PARTITION BY id
          ORDER BY CASE MOD (id, 2) WHEN 1 THEN colval END,
                   CASE MOD (id, 2) WHEN 0 THEN colval END DESC) r
  FROM x UNPIVOT (colval FOR colname
         IN (col1 AS 'col1', col2 AS 'col2', col3 AS 'col3', col4 AS 'col4',
             col5 AS 'col5', col6 AS 'col6', col7 AS 'col7')
             )
)
SELECT * FROM pivoted
PIVOT (MAX (colval)
           FOR r
           IN (1 AS col1, 2 AS col2, 3 AS col3, 4 AS col4,
               5 AS col5, 6 AS col6, 7 AS col7))

Results

| ID | COL1 | COL2 | COL3 | COL4 | COL5 | COL6 | COL7 |
|----|------|------|------|------|------|------|------|
|  1 |    3 |    4 |    4 |    6 |    7 |    8 |    8 |
|  2 |    9 |    8 |    7 |    7 |    5 |    2 |    1 |
|  3 |    1 |    2 |    4 |    5 |    7 |    8 |    9 |
|  4 |    9 |    8 |    7 |    4 |    4 |    4 |    1 |
|  5 |    2 |    2 |    4 |    5 |    5 |    6 |    7 |

【讨论】:

  • 谢谢,但我需要一个可以处理任意数量列的代码,表格是动态的,这就是为什么我不能使用代码来指定每一列的原因。如果我添加 10 列,例如,我必须更改代码。
猜你喜欢
  • 1970-01-01
  • 2021-10-27
  • 2019-08-10
  • 1970-01-01
  • 2017-06-15
  • 1970-01-01
  • 2011-07-09
相关资源
最近更新 更多