繁体   English   中英

将多行合并为一行,Oracle

[英]Combining multiple rows into one row, Oracle

我正在使用在Oracle中创建并通过SDE在GIS软件中使用的数据库。 我的共谋之一是要从该数据库中进行一些统计,而我无法找到一个合理的SQL查询来获取数据。

我有两张桌子,一张带有注册信息,一张带有注册详细信息。 这是一对多的关系,因此注册可以具有一个或多个与其相关的详细信息(没有最大数量)。

  1. 表:注册
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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM