![](/img/trans.png)
[英]Oracle SQl Developer - Combining multiple rows into one row based on conditions
[英]Combining multiple rows into one row, Oracle
我正在使用在Oracle中创建并通过SDE在GIS软件中使用的数据库。 我的共谋之一是要从该数据库中进行一些统计,而我无法找到一个合理的SQL查询来获取数据。
我有两张桌子,一张带有注册信息,一张带有注册详细信息。 这是一对多的关系,因此注册可以具有一个或多个与其相关的详细信息(没有最大数量)。
RegistrationID Date TotLenght 1 01.01.2010 5 2 01.02.2010 15 3 05.02.2009 10
2.表:RegistrationDetail
DetailID RegistrationID Owner Type Distance 1 1 TD UB 1,5 2 1 AB US 2 3 1 TD UQ 4 4 2 AB UQ 13 5 2 AB UR 13,1 6 3 TD US 5
我希望结果选择如下所示:
RegistrationID Date TotLenght DetailID RegistrationID Owner Type Distance DetailID RegistrationID Owner Type Distance DetailID RegistrationID Owner Type Distance 1 01.01.2010 5 1 1 TD UB 1,5 2 1 AB US 2 3 1 TD UQ 4 2 01.02.2010 15 4 2 AB UQ 13 5 2 AB UR 13,1 3 05.02.2009 10 6 3 TD US 5
使用普通联接,每个注册和详细信息都会得到一行。 谁能帮我这个? 我没有数据库的管理员权限,因此无法创建任何表或变量。 如果可能,我可以将表复制到Access中。
如果明细记录的最大数量是固定的并且已知,则可以这样做。 数字越大,查询要编写的代码就越繁琐。 这就是大自然给我们剪切粘贴的原因。
以下查询使用了两个技巧。 Common Table Expression(又名Sub-Query Factoring)子句将查询封装在RegistrationDetail上,因此我们可以轻松地在多个地方引用它。 子查询使用解析函数ROW_NUMBER(),它使我们能够识别RegistrationID组中的每个明细记录。 这两个功能都是Oracle 9i中引入的,因此并不是新功能,但是很多人仍然不了解它们。
主查询使用外部联接将Registration表多次连接到子查询中的行。 它加入RegistrationID和派生的DetNo。
SQL> with dets as
2 ( select
3 registrationid
4 , owner
5 , type
6 , distance
7 , detailid
8 , row_number() over (partition by registrationid
9 order by detailid) as detno
10 from registrationdetail )
11 select
12 reg.registrationid
13 , reg.somedate
14 , reg.totlength
15 , det1.detailid as detId1
16 , det1.owner as owner1
17 , det1.type as type1
18 , det1.distance as distance1
19 , det2.detailid as detId2
20 , det2.owner as owner2
21 , det2.type as type2
22 , det2.distance as distance2
23 , det3.detailid as detId3
24 , det3.owner as owner3
25 , det3.type as type3
26 , det3.distance as distance3
27 from registration reg
28 left join dets det1 on ( reg.registrationid = det1.registrationid
29 and det1.detno = 1 )
30 left join dets det2 on ( reg.registrationid = det2.registrationid
31 and det2.detno = 2 )
32 left join dets det3 on ( reg.registrationid = det3.registrationid
33 and det3.detno = 3 )
34 order by reg.registrationid
35 /
REGISTRATIONID SOMEDATE TOTLENGTH DETID1 OW TY DISTANCE1 DETID2 OW TY DISTANCE2 DETID3 OW TY DISTANCE3
-------------- --------- ---------- ---------- -- -- ---------- ---------- -- -- ---------- ---------- -- -- ----------
1 01-JAN-10 5 1 TD UB 1.5 2 AB US 2 3 TD UQ 4
2 01-FEB-10 15 4 AB UQ 13 5 AB UR 13.1
3 05-FEB-09 10 6 TD US 5
SQL>
显然,如果每个RegistrationID具有四个Detail记录,则将需要其中四个外部联接(以及投影中的四组列)。
编辑
我刚刚重新阅读了您的问题,发现了可怕的单词“没有最大数量”。 抱歉,那样的话您不走运。 使用可变数量的集合解决此问题的唯一方法是使用动态SQL,您已经有效地将其排除在外(因为您需要创建其他架构对象)。
编辑2
还有另一种解决方案,就是提取数据并忽略布局。 Oracle允许我们在标量旁边的投影中声明内联游标,即嵌套的select
语句。 这将显示输出的问题传递给客户端工具。
在此版本中,我使用Oracle的内置XML功能来生成输出(基于当今许多工具可以呈现XML的基础)。 RegistrationDetails记录在称为REG_DETAILS的XMLElement中分组,该XMLElement嵌套在每个Registration记录中。
with dets as
( select
registrationid
, owner
, type
, distance
, detailid
, row_number() over (partition by registrationid
order by detailid) as detno
from registrationdetail )
select
xmlelement("AllRegistrations"
, xmlagg(
xmlelement("Registration"
, xmlforest( reg.registrationid
, reg.somedate
, reg.totlength
, ( select xmlagg(
xmlelement("RegDetail"
, xmlforest(dets.detailid
, dets.owner
, dets.type
, dets.distance
, dets.detno
)
)
)
from dets
where reg.registrationid = dets.registrationid
) as "RegDetails"
)
)
)
)
from registration reg
order by reg.registrationid
/
在同一查询中,不能有多个具有相同名称的列-oracle将它们重命名为“ Date_1”,“ Date_2”等。多行有什么问题? 您如何访问它?
SELECT
wo_h.event_perfno_i AS WO,
wo_h.ata_chapter,
wo_h.created_by AS WorkOrderCreator,
wo_h.issue_date As Work_Order_IssueDate,
wo_h.ac_registr As WorkOrderACRegister,
wo_h.state As WorkOrderState,
('Created By:'||wsl.workstep_sign||' On') As Description,
wsl.workstep_date,
listagg('Action Performed By,' ||woa.mutator||'At date' ||
SELECT
wo_h.event_perfno_i AS WO,
wo_h.ata_chapter,
wo_h.created_by AS WorkOrderCreator,
wo_h.issue_date As Work_Order_IssueDate,
wo_h.ac_registr As WorkOrderACRegister,
wo_h.state As WorkOrderState,
('Created By:'||wsl.workstep_sign||' On') As Description,
wsl.workstep_date,
listagg('Action Performed By,' ||woa.mutator||'At date' || woa.action_date|| '.'|| woa.text,'.. ') WITHIN GROUP ( ORDER BY woa.text)
FROM workstep_link wsl
join wo_header wo_h on wsl.event_perfno_i=wo_h.event_perfno_i
join wo_text_action woa on wsl.workstep_linkno_i=woa.workstep_linkno_i
WHERE
wo_h.state = 'O'
AND wo_h.event_perfno_i = '5690136'
AND wo_h.ac_registr = 'AEC'
GROUP BY wo_h.event_perfno_i, wo_h.ata_chapter, wo_h.created_by,wo_h.issue_date,wo_h.ac_registr,wo_h.state,wsl.workstep_date,
wsl.workstep_time,
wsl.workstep_sign
woa.action_date|| '.'|| woa.text,'.. ') WITHIN GROUP ( ORDER BY woa.text)
FROM workstep_link wsl
join wo_header wo_h on wsl.event_perfno_i=wo_h.event_perfno_i
join wo_text_action woa on wsl.workstep_linkno_i=woa.workstep_linkno_i
WHERE
wo_h.state = 'O'
AND wo_h.event_perfno_i = '5690136'
AND wo_h.ac_registr = 'AEC'
GROUP BY wo_h.event_perfno_i, wo_h.ata_chapter, wo_h.created_by,wo_h.issue_date,wo_h.ac_registr,wo_h.state,wsl.workstep_date,
wsl.workstep_time,
wsl.workstep_sign
SELECT
wo_h.event_perfno_i AS WO,
wo_h.ata_chapter,
wo_h.created_by AS WorkOrderCreator,
wo_h.issue_date As Work_Order_IssueDate,
wo_h.ac_registr As WorkOrderACRegister,
wo_h.state As WorkOrderState,
('Created By:'||wsl.workstep_sign||' On') As Description,
wsl.workstep_date,
listagg('Action Performed By,' ||woa.mutator||'At date' || woa.action_date|| '.'|| woa.text,'.. ') WITHIN GROUP ( ORDER BY woa.text)
FROM workstep_link wsl
join wo_header wo_h on wsl.event_perfno_i=wo_h.event_perfno_i
join wo_text_action woa on wsl.workstep_linkno_i=woa.workstep_linkno_i
WHERE
wo_h.state = 'O'
AND wo_h.event_perfno_i = '5690136'
AND wo_h.ac_registr = 'AEC'
GROUP BY wo_h.event_perfno_i, wo_h.ata_chapter, wo_h.created_by,wo_h.issue_date,wo_h.ac_registr,wo_h.state,wsl.workstep_date,
wsl.workstep_time,
wsl.workstep_sign
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.