Oracle:获取多列上的前n个值的列名

Oracle:获取多列上的前n个值的列名,oracle,pivot,max,Oracle,Pivot,Max,我的问题类似于 在我的查询中,我需要3个不同列的最大值 示例:列1=10、列2=20、列3=30>输出应 30岁。我需要这个最大值来对列表进行排序 但是,我需要的不是实际值,而是列名,理想情况下,不只是max-one,而是top-3作为示例 所需的输出将是 ID first second third ------------------------------- 1 column 3 column 2 column1 不确定是否有更好的方法,但这里有一个可能的解决

我的问题类似于

在我的查询中,我需要3个不同列的最大值

示例:列1=10、列2=20、列3=30>输出应 30岁。我需要这个最大值来对列表进行排序

但是,我需要的不是实际值,而是列名,理想情况下,不只是max-one,而是top-3作为示例

所需的输出将是

ID    first    second    third
-------------------------------
1    column 3  column 2  column1

不确定是否有更好的方法,但这里有一个可能的解决方案,使用CASE语句。下面是我测试过的表结构:

CREATE TABLE MAX_COL(
  "ID" INT,
  COLUMN_1 INT,
  COLUMN_2 INT,
  COLUMN_3 INT
);
下面是我使用的SQL:

SELECT 
  "ID",
  CASE
    WHEN COLUMN_1 > COLUMN_2 AND COLUMN_1 > COLUMN_3 THEN 'COLUMN_1'
    WHEN COLUMN_2 > COLUMN_1 AND COLUMN_2 > COLUMN_3 THEN 'COLUMN_2'
    WHEN COLUMN_3 > COLUMN_2 AND COLUMN_3 > COLUMN_1 THEN 'COLUMN_3'
    ELSE 'NONE'
  END AS "FIRST",
  CASE
    WHEN COLUMN_1 > COLUMN_2 AND COLUMN_1 < COLUMN_3 THEN 'COLUMN_1'
    WHEN COLUMN_2 > COLUMN_1 AND COLUMN_2 < COLUMN_3 THEN 'COLUMN_2'
    WHEN COLUMN_3 > COLUMN_2 AND COLUMN_3 < COLUMN_1 THEN 'COLUMN_3'
    ELSE 'NONE'
  END AS "SECOND",
  CASE
    WHEN COLUMN_1 < COLUMN_2 AND COLUMN_1 < COLUMN_3 THEN 'COLUMN_1'
    WHEN COLUMN_2 < COLUMN_1 AND COLUMN_2 < COLUMN_3 THEN 'COLUMN_2'
    WHEN COLUMN_3 < COLUMN_2 AND COLUMN_3 < COLUMN_1 THEN 'COLUMN_3'
    ELSE 'NONE'
  END AS "THIRD"
FROM 
  MAX_COL;
此示例只有3列,但您可以轻松添加更多列。然后,您可以在如下查询中使用:

SELECT 
  MAX_COL.*, 
  COLUMN_POSITION(ID, 1) AS "FIRST",
  COLUMN_POSITION(ID, 2) AS "SECOND", 
  COLUMN_POSITION(ID, 3) AS "THIRD" 
FROM MAX_COL

对于您所请求的内容,没有内置函数。所以user1578653的答案是好的,直接的,快速的。另一种方法是使用PL/SQL编写函数

如果您希望使用纯SQL,但希望更轻松地将列添加到比较中,那么如果您仅对两列(id和列名字符串)感到满意,则可以执行以下操作:

select id, listagg(colname, ', ') within group (order by value desc) as columns
from
(
  select id, 'column1' as colname, col1 as value from mytable
  union all
  select id, 'column2' as colname, col2 as value from mytable
  union all
  select id, 'column3' as colname, col3 as value from mytable
  -- add more columns here, if you wish
)
group by id;
请注意,这比user1578653的SQL语句慢,因为该表被读取了三次。(我在这里也会以不同的方式对待相等的值,相同的值会导致随机顺序。)

您可以使用它

首先取消拆分表,并使用降序排列的值分配秩

create table sample(
  id number,
  col1 number,
  col2 number,
  col3 number
  );

insert into sample values(1,10,20,30);
insert into sample values(2,10,20,15);

select id, col_name, val,
       row_number() over (partition by id order by val desc) r
from sample
unpivot(val for col_name in (
        col1 AS 'col1', col2 AS 'col2', col3 AS 'col3')
       );
输出:

| ID | COL_NAME | VAL | R |
|----|----------|-----|---|
|  1 |     col3 |  30 | 1 |
|  1 |     col2 |  20 | 2 |
|  1 |     col1 |  10 | 3 |
|  2 |     col2 |  20 | 1 |
|  2 |     col3 |  15 | 2 |
|  2 |     col1 |  10 | 3 |
| ID | FIRST | SECOND | THIRD |
|----|-------|--------|-------|
|  1 |  col3 |   col2 |  col1 |
|  2 |  col2 |   col3 |  col1 |

下一步,根据排名列透视列名称

with x(id, col_name, val,r) as (
  select id, col_name, val,
         row_number() over (partition by id order by val desc)
  from sample
  unpivot(val for col_name in (
          col1 AS 'col1', col2 AS 'col2', col3 AS 'col3')
         )
  )
select * from (
  select id, col_name, r
  from x
  )
pivot(max(col_name) for r in (
  1 as first, 2 as second, 3 as third)
      );
输出:

| ID | COL_NAME | VAL | R |
|----|----------|-----|---|
|  1 |     col3 |  30 | 1 |
|  1 |     col2 |  20 | 2 |
|  1 |     col1 |  10 | 3 |
|  2 |     col2 |  20 | 1 |
|  2 |     col3 |  15 | 2 |
|  2 |     col1 |  10 | 3 |
| ID | FIRST | SECOND | THIRD |
|----|-------|--------|-------|
|  1 |  col3 |   col2 |  col1 |
|  2 |  col2 |   col3 |  col1 |
.

选择 (案例 当A>B和A>C时,则“A” 当B>A和B>C时,则“B” 当C>B和C>A时,则为“C” 结束)作为“最大值\u列\u名称”, 最大值(A、B、C)作为最大搜索中的最大值


--table name=max\u search和column\u name分别是A、B和C。在我的例子中,它有30多列,这使得它变得相当不切实际。遗憾的是,应用程序仍然在Oracle 10上,它还没有pivot/unpivot功能。