【问题标题】:Display 1 column values to 3 different columns in Oracle 11g在 Oracle 11g 中将 1 列值显示到 3 个不同的列
【发布时间】:2021-03-29 06:11:01
【问题描述】:

大家好,我是 usnig sql 11g。我遇到了一种情况,我的表有 1 个这样的列

column1
1
john
2000
2
david
4000
4
eon
5000

我希望输出分成 3 个不同的列,例如

id     name     salary
1      john      2000
2      david     3000
4      eon       5000

【问题讨论】:

  • 我怀疑是关于 Oracle 11G
  • 只有 11g...
  • 嗨@Avinash,如果有完整的表定义脚本会很不错。问题是数据库死了不保证要返回的行的顺序,除非正在使用“order by”。因此,我们至少需要查看一列来对数据进行排序,或者我们可能会找到更简单的方法来帮助您
  • SQL 表代表 无序 集。您的转换似乎需要对行进行排序 - 但该信息需要在列中,而不是在数据中。你不能用你显示的数据做你想做的事。

标签: sql oracle oracle11g


【解决方案1】:

如果只有表格中的 1 列,您将很难获得所需的输出。在 SQL 表中,表是“无序集”,因此无法保证数据将按照您在上面显示的完全相同的顺序提取 - 但要获得所需的输出,我们必须具有可靠的行顺序。

假设该表中没有其他列,我建议您需要添加一个 ID 列,如下所示:

alter table mytable
add (
    id NUMBER GENERATED BY DEFAULT AS IDENTITY
    )

+---------+----+
| COLUMN1 | ID |
+---------+----+
| 1       |  1 |
| john    |  2 |
| 2000    |  3 |
| 2       |  4 |
| david   |  5 |
| 4000    |  6 |
| 4       |  7 |
| eon     |  8 |
| 5000    |  9 |
+---------+----+

其中(希望)将添加我们可以用来帮助排序输出的信息:

在下面我们使用滞后 1 行,领先 1 行将数据扩展为 3 列,然后在 id 列上使用 3 的模数仅选择在所有 3 列中都有值的所需行:

select id, name, salary
from (
    select 
      mod(id,3) AS mod3
    , lag(column1, 1) over(order by id)  as id
    , column1                            as name
    , lead(column1, 1) over(order by id) as salary
    from mytable
)
where mod3 = 2

+----+-------+--------+
| ID | NAME  | SALARY |
+----+-------+--------+
|  1 | john  |   2000 |
|  2 | david |   4000 |
|  4 | eon   |   5000 |
+----+-------+--------+

demo

【讨论】:

    【解决方案2】:

    架构:

     create table table1 (column1 varchar(50));
    
     insert into table1
     with cte as (select '1'from dual
     union all
     select 'john' from dual
     union all
     select '2000'from dual
     union all
     select '2'from dual
     union all
     select 'david'from dual
     union all
     select '4000'from dual
     union all
     select '4'from dual
     union all
     select 'eon'from dual
     union all
     select '5000'from dual
     )
      select * from cte
    

    查询:

     with cte as 
     (
         select column1,( ( Row_number()OVER(ORDER BY 1 ) - 1 ) / 3 ) + 1 rn from table1
     )
     , cte2 as
     (
         select column1,rn, row_number()over(partition by NVL(SUBSTR(rn, 0, INSTR(rn, '.')-1), rn) order by rn) rnk  ,NVL(SUBSTR(rn, 0, INSTR(rn, '.')-1), rn)grp
         from cte 
     )
     select max("1")ID,max("2")Name,max("3")Salary from(
     select *  from cte2)
     pivot (max(column1) for rnk in (1,2,3))
     group by grp
     order by grp
     
    

    输出:

    ID NAME SALARY
    1 john 2000
    2 david 4000
    4 eon 5000

    db小提琴here

    【讨论】:

    • order by 1 没有模仿想要的顺序,可惜结果不可靠,试试吧
    • 是的,我知道订单无法保证。但是稍后添加标识列是否总是保证顺序?
    • 添加身份并不能保证最初的顺序正确,但会为订购建立一致的基础。
    • @Avihash 希望您的问题已经解决。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 2014-12-08
    • 1970-01-01
    • 2014-12-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多