Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle 11 SQL:将1行拆分为x行并插入新列_Sql_Oracle_Unpivot - Fatal编程技术网

Oracle 11 SQL:将1行拆分为x行并插入新列

Oracle 11 SQL:将1行拆分为x行并插入新列,sql,oracle,unpivot,Sql,Oracle,Unpivot,我问了,这个问题很接近,但有一个小转折 客户要求将Oracle DB SQL中的1行拆分为6行 比如说,最初SQL(具有多个连接的复杂SQL)包含9列: select A, B, C, D, E, F, G, H, I from X, Y, Z . . . (但查询相当复杂) 现在,客户要求返回上述模式的每一行,新输出应如下所示: 1) A, B, C, 'Name for D : ', D 2) A, B, C, 'Name for E : ', E 3) A, B, C,

我问了,这个问题很接近,但有一个小转折

客户要求将Oracle DB SQL中的1行拆分为6行

比如说,最初SQL(具有多个连接的复杂SQL)包含9列:

select A, B, C, D, E, F, G, H, I  
   from X, Y, Z . . .
(但查询相当复杂)

现在,客户要求返回上述模式的每一行,新输出应如下所示:

1) A, B, C, 'Name for D : ', D  
2) A, B, C, 'Name for E : ', E  
3) A, B, C, 'Name for F : ', F  
4) A, B, C, 'Name for G : ', G  
5) A, B, C, 'Name for H : ', H  
6) A, B, C, 'Name for I : ', I  
基本上,前3列的值将在所有6个新行中重复。
新行的第4列将是一个字符串,表示第5列的内容

该过程对原始查询中的每一行重复

从前面的回答中,我知道unpivot可以做到这一点——只是我自己无法解决这个问题

更新:

实际上,在我的问题中,我不清楚我想要的第4列的输出不是直接的连接。如果是这样的话,我可以自己做。这些值不是D、E、F、G、H、I的文字串联。
D、E、F、G、H、I的第四列值如何?如下所示: 列侬, 保罗·麦卡特尼, 林戈·斯塔尔, 乔治·哈里森, 皮特·贝斯特, 汤米·摩尔

因此,输出现在将如下所示:

1) A, B, C, 'Lennon : ', D  
2) A, B, C, 'paul McCartney : ', E  
3) A, B, C, 'Ringo Starr : ', F  
4) A, B, C, 'George Harrison : ', G  
5) A, B, C, 'Pete Best : ', H  
6) A, B, C, 'Tommy Moore : ', I  
我希望您能理解第4列的值可以是任何字符串,而不是第5列的导数

更新2:
假设,为了便于说明,我的复杂查询可以简化为

假设我在Emp和Dept表上运行以下SQL:

select emp.empno, emp.ename, emp.job, emp.mgr, emp.hiredate, emp.sal , dept.deptno, dept.dname, dept.loc from emp, dept where emp.deptno = dept.deptno;  
在我的情况下,第4栏将是“经理”、“雇佣”、“sal”、“deptno”、“dname”和“loc”

因此,例如,对于上述查询中的以下(原始)结果行:
雇员、雇员、职务、经理、雇佣人员、sal、deptno、dname、loc
7698,布莱克,经理,78391981-05-012850.00,30,芝加哥销售部

新的6行将是
7698布莱克经理7839
7698布莱克经理雇佣日期1981-05-01
7698布莱克经理sal 2850.00
7698布莱克经理部30
7698 BLAKE经理数据名称销售
7698布莱克经理,芝加哥


我应该如何转换上述SQL以获得上述新的6行?

您可以使用unpivot子句。我认为该代码将帮助您:

select a,b,c,'Name for ' || name_code || ' : '|| name_code as value  from 
(select 'A' a ,'B' b ,'C' c ,'D' d,'E' e,'F' f,'G' g,'H' h,'I' i from dual) 
unpivot include nulls 
(
name_for for name_code in (d as 'D', e as 'E' ,f as 'F',g as 'G',h  as 'H',i as 'I') 
);
问题更新后。答案改为:

select A,B,C,'Name for ' || name_for  as value, name_code  from 
(select 1 A,2 B,3 C,'Lennon' D,'Paul McCartney' E, 'Ringo Starr' F, 
              null G, 'Pete Best'H, 'Tommy Moore'  I from dual )
unpivot include nulls 
(
name_for for name_code in (d,e,f,g,h,i) 
)

您可以将
unpivot
concat()
函数
concat(concat('Name for',val),':')
或串联运算符(
| |
)一起使用,作为
'Name for'| val | |':'

with t(a,b,c,d,e,f,g,h,i) as
(
 select 1,2,3,'Lennon','Paul McCartney', 'Ringo Starr', 
              null, 'Pete Best', 'Tommy Moore' 
   from dual 
)
select a,b,c, concat( concat('Name for ',val),' : ') as explanation,
       col 
  from
  (
   select nvl(to_char(a),' ') as a, nvl(to_char(b),' ') as b,
          nvl(to_char(c),' ') as c, nvl(to_char(d),' ') as d, 
          nvl(to_char(e),' ') as e, nvl(to_char(f),' ') as f, 
          nvl(to_char(g),' ') as g, nvl(to_char(h),' ') as h, 
          nvl(to_char(i),' ') as i
    from t
  )  
  unpivot 
  ( val for col in (d,e,f,g,h,i) )
  order by col

更新2:根据您的新案例,查询可以重新排列为:


关于UPDATE2,这似乎确实返回了所需的输出:

with o as (select emp.empno, emp.ename, emp.job, emp.mgr, emp.hiredate, emp.sal , dept.deptno, dept.dname, dept.loc from emp, dept where emp.deptno = dept.deptno)
select o.empno, o.ename, o.job, j.column_name, j.value FROM o inner join (
 select o.empno, 'MGR'  as column_name, TO_CHAR(o.mgr)  as value  FROM o UNION ALL
 select o.empno, 'HIREDATE', TO_CHAR(o.hiredate) FROM o UNION ALL
 select o.empno, 'SAL', TO_CHAR(o.sal) FROM o UNION ALL
 select o.empno, 'DEPTNO', TO_CHAR(o.deptno) FROM o UNION ALL
 select o.empno, 'DNAME', TO_CHAR(o.dname) FROM o UNION ALL
 select o.empno, 'LOC', TO_CHAR(o.loc) FROM o) j
 on (o.empno = j.empno)
 order by o.empno;
但是,不能使用动态列数,并且所有“值”必须可转换为字符串。
我不确定如果没有动态SQL,您是否可以做得更进一步。

只是为了一些不同的东西,这也可以用“老式的方式”(即,不使用
UNPIVOT
)来完成


在这种方法中,将复杂查询交叉连接到行生成器(
SELECT rownum FROM DUAL CONNECT BY rownum如果结果必须具体化,最简单的方法是使用
INSERT ALL

INSERT ALL
INTO t(empno, ename, job, "key", "value") VALUES (empno, ename, job, 'mgr', mgr)
INTO t(empno, ename, job, "key", "value") VALUES (empno, ename, job, 'hiredate', hiredate)
INTO t(empno, ename, job, "key", "value") VALUES (empno, ename, job, 'sal', sal)
INTO t(empno, ename, job, "key", "value") VALUES (empno, ename, job, 'deptno', deptno)
INTO t(empno, ename, job, "key", "value") VALUES (empno, ename, job, 'dname', dname)
INTO t(empno, ename, job, "key", "value") VALUES (empno, ename, job, 'loc', loc)
select emp.empno, emp.ename, emp.job, emp.mgr, emp.hiredate, emp.sal
      ,dept.deptno, dept.dname, dept.loc 
from emp
join dept 
 on emp.deptno = dept.deptno;

SELECT * FROM t;

和xquery的黑暗面;)

大查询为(选择7698 empno,'BLAKE'ename,'经理'职务,7839经理,截止日期('1981-05-01','yyyy-mm-dd')hiredate,2850.00 sal,30 deptno,'SALES'dname,'CHICAGO'loc
联合所有
选择7698 empno,'BLAKE2'ename,'MANAGER2'职务,7839经理,截止日期('1981-05-01','yyyy-mm-dd')雇佣,2850.00 sal,30 deptno,'SALES2'dname,'CHICAGO2'loc从dual
),
xmlwrap as(从big_查询中选择xmlforest(EMPNO、ENAME、JOB、MGR、HIREDATE、SAL、DEPTNO、DNAME、LOC)xml_体)
从xmlwrap,xmltable('中的$i)中选择x.*(4到9)
返回(
{$doc/*[1]/text()}
{$doc/*[2]/text()}
{$doc/*[3]/text()}
{concat(“Name for”,$doc/*[$i]/Name())}
{$doc/*[$i]/text()}
) 
' 
将xml_正文作为“doc”传递
柱
“C1”varchar2(100)路径“/行/C1”,
“C2”varchar2(100)路径“/行/C2”,
“C3”varchar2(100)路径“/ROW/C3”,
“C4”varchar2(100)路径“/行/C4”,
“C5”varchar2(100)路径“/行/C5”
)x;

xmlforest
-将列按正确顺序放在此处,并更改大查询

这在员工和部门人力资源表上对我很有用 但首先,所有列都需要在with子句中转换为char

这是我的SQL

with a as (select emp.employee_id, emp.first_name, emp.job_id, to_char(emp.MANAGER_ID) as MANAGER_ID, 
to_char(emp.HIRE_DATE,'YYYYMMDD') as HIRE_DATE, to_char(emp.salary) as salary, 
to_char(dept.department_id) as department_id , 
to_char(dept.department_name) as department_name ,
to_char(dept.location_id) as location_id 
from HR.employees emp, HR.departments dept where emp.department_id = dept.department_id)
select * from a 
unpivot 
(Value for Detail in ( MANAGER_ID as 'MANAGER_ID',
HIRE_DATE as 'HIRE_DATE',salary as 'SALARY', 
department_id as 'department_id',
department_name as 'department_name',
location_id as 'location_id'));

您可以为主查询提供别名或将其放入with子句中,然后将其连接到从中生成的未插入表:
select main.a,main.b,main.c,“| unpivoted.col | | | |的名称:”,unpivoted.col from main,unpivoted where unpivoted.col not in(main.a,main.b,main.c)
在本例中,
unpivoted
可以是一个子查询,为您提供所需的
main
@grog的unpivoted:我更新了我的问题以澄清。请。看看更新。我明白了,那么,这些值是从哪里来的呢?如果您将它们存储在某个地方(希望不是作为列名),那么就可以实现我更新了问题以澄清什么是reall
select your_complex_query.empno, your_complex_query.ename, your_complex_query.job, 
       DECODE(rn, 1, 'mgr',
                  2, 'hiredate',
                  3, 'sal',
                  4, 'deptno',
                  5, 'dname',
                  6, 'loc',
                  '*error: unmapped*') row_description,
       DECODE(rn, 1, to_char(your_complex_query.mgr),
                  2, to_char(your_complex_query.hiredate, 'DD-MON-YYYY'),
                  3, to_char(your_complex_query.sal, 'FM999,990.00'),
                  4, to_char(your_complex_query.deptno),
                  5, your_complex_query.dname,
                  6, your_complex_query.loc,
                  '*error: unmapped*') row_value
from ( select emp.empno, emp.ename, emp.job, emp.mgr, emp.hiredate, emp.sal , dept.deptno, dept.dname, dept.loc from scott.emp, scott.dept where emp.deptno = dept.deptno) your_complex_query, 
     ( SELECT rownum rn FROM dual CONNECT BY rownum <= 6 ) rn
;
+-------+-------+-----------+-----------------+------------+
| EMPNO | ENAME |    JOB    | ROW_DESCRIPTION | ROW_VALUE  |
+-------+-------+-----------+-----------------+------------+
|  7839 | KING  | PRESIDENT | mgr             |  -         |
|  7839 | KING  | PRESIDENT | hiredate        | 17-Nov-81  |
|  7839 | KING  | PRESIDENT | sal             | 5,000.00   |
|  7839 | KING  | PRESIDENT | deptno          | 10         |
|  7839 | KING  | PRESIDENT | dname           | ACCOUNTING |
|  7839 | KING  | PRESIDENT | loc             | NEW YORK   |
|  7698 | BLAKE | MANAGER   | mgr             | 7839       |
|  7698 | BLAKE | MANAGER   | hiredate        | 1-May-81   |
|  7698 | BLAKE | MANAGER   | sal             | 2,850.00   |
|  7698 | BLAKE | MANAGER   | deptno          | 30         |
|  7698 | BLAKE | MANAGER   | dname           | SALES      |
|  7698 | BLAKE | MANAGER   | loc             | CHICAGO    |
|  7782 | CLARK | MANAGER   | mgr             | 7839       |
|  7782 | CLARK | MANAGER   | hiredate        | 9-Jun-81   |
|  7782 | CLARK | MANAGER   | sal             | 2,450.00   |
|  7782 | CLARK | MANAGER   | deptno          | 10         |
|  7782 | CLARK | MANAGER   | dname           | ACCOUNTING |
|  7782 | CLARK | MANAGER   | loc             | NEW YORK   |
|  7566 | JONES | MANAGER   | mgr             | 7839       |
|  7566 | JONES | MANAGER   | hiredate        | 2-Apr-81   |
|  7566 | JONES | MANAGER   | sal             | 2,975.00   |
|  7566 | JONES | MANAGER   | deptno          | 20         |
|  7566 | JONES | MANAGER   | dname           | RESEARCH   |
|  7566 | JONES | MANAGER   | loc             | DALLAS     |
|  7788 | SCOTT | ANALYST   | mgr             | 7566       |
|  7788 | SCOTT | ANALYST   | hiredate        | 19-Apr-87  |
|  7788 | SCOTT | ANALYST   | sal             | 3,000.00   |
|  7788 | SCOTT | ANALYST   | deptno          | 20         |
|  7788 | SCOTT | ANALYST   | dname           | RESEARCH   |
|  7788 | SCOTT | ANALYST   | loc             | DALLAS     |
|  7902 | FORD  | ANALYST   | mgr             | 7566       |
|  7902 | FORD  | ANALYST   | hiredate        | 3-Dec-81   |
|  7902 | FORD  | ANALYST   | sal             | 3,000.00   |
|  7902 | FORD  | ANALYST   | deptno          | 20         |
|  7902 | FORD  | ANALYST   | dname           | RESEARCH   |
|  7902 | FORD  | ANALYST   | loc             | DALLAS     |
|  7369 | SMITH | CLERK     | mgr             | 7902       |
|  7369 | SMITH | CLERK     | hiredate        | 17-Dec-80  |
|  7369 | SMITH | CLERK     | sal             | 800        |
|  7369 | SMITH | CLERK     | deptno          | 20         |
|  7369 | SMITH | CLERK     | dname           | RESEARCH   |
|  7369 | SMITH | CLERK     | loc             | DALLAS     |
|  7499 | ALLEN | SALESMAN  | mgr             | 7698       |
|  7499 | ALLEN | SALESMAN  | hiredate        | 20-Feb-81  |
|  7499 | ALLEN | SALESMAN  | sal             | 1,600.00   |
|  7499 | ALLEN | SALESMAN  | deptno          | 30         |
|  7499 | ALLEN | SALESMAN  | dname           | SALES      |
|  7499 | ALLEN | SALESMAN  | loc             | CHICAGO    |
|  7521 | WARD  | SALESMAN  | mgr             | 7698       |
|  7521 | WARD  | SALESMAN  | hiredate        | 22-Feb-81  |
+-------+-------+-----------+-----------------+------------+
INSERT ALL
INTO t(empno, ename, job, "key", "value") VALUES (empno, ename, job, 'mgr', mgr)
INTO t(empno, ename, job, "key", "value") VALUES (empno, ename, job, 'hiredate', hiredate)
INTO t(empno, ename, job, "key", "value") VALUES (empno, ename, job, 'sal', sal)
INTO t(empno, ename, job, "key", "value") VALUES (empno, ename, job, 'deptno', deptno)
INTO t(empno, ename, job, "key", "value") VALUES (empno, ename, job, 'dname', dname)
INTO t(empno, ename, job, "key", "value") VALUES (empno, ename, job, 'loc', loc)
select emp.empno, emp.ename, emp.job, emp.mgr, emp.hiredate, emp.sal
      ,dept.deptno, dept.dname, dept.loc 
from emp
join dept 
 on emp.deptno = dept.deptno;

SELECT * FROM t;
with big_query as (select 7698 empno, 'BLAKE' ename, 'MANAGER' job, 7839 mgr, to_date('1981-05-01','yyyy-mm-dd') hiredate, 2850.00 sal , 30 deptno, 'SALES' dname, 'CHICAGO' loc from dual
union all
select 7698 empno, 'BLAKE2' ename, 'MANAGER2' job, 7839 mgr, to_date('1981-05-01','yyyy-mm-dd') hiredate, 2850.00 sal , 30 deptno, 'SALES2' dname, 'CHICAGO2' loc from dual 
),
xmlwrap as (select xmlforest(EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,DEPTNO,DNAME,LOC) xml_body from big_query)

select x.* from xmlwrap,xmltable('for $i in (4 to 9) 
                                return(
                                <ROW>
                                    <C1>{$doc/*[1]/text()}</C1>
                                    <C2>{$doc/*[2]/text()}</C2>
                                    <C3>{$doc/*[3]/text()}</C3>
                                    <C4>{concat("Name for ", $doc/*[$i]/name())}</C4>
                                    <C5>{$doc/*[$i]/text()}</C5>                                       
                                </ROW>                                                   
                                ) 
                                    ' 
                            passing xml_body as "doc"                   
                            COLUMNS 
                             "C1" varchar2(100) PATH '/ROW/C1',
                             "C2" varchar2(100) PATH '/ROW/C2',
                             "C3" varchar2(100) PATH '/ROW/C3',
                             "C4" varchar2(100) PATH '/ROW/C4',
                             "C5" varchar2(100) PATH '/ROW/C5'
                            ) x;
with a as (select emp.employee_id, emp.first_name, emp.job_id, to_char(emp.MANAGER_ID) as MANAGER_ID, 
to_char(emp.HIRE_DATE,'YYYYMMDD') as HIRE_DATE, to_char(emp.salary) as salary, 
to_char(dept.department_id) as department_id , 
to_char(dept.department_name) as department_name ,
to_char(dept.location_id) as location_id 
from HR.employees emp, HR.departments dept where emp.department_id = dept.department_id)
select * from a 
unpivot 
(Value for Detail in ( MANAGER_ID as 'MANAGER_ID',
HIRE_DATE as 'HIRE_DATE',salary as 'SALARY', 
department_id as 'department_id',
department_name as 'department_name',
location_id as 'location_id'));