2010-04-22 3 views
1

Я работаю с базой данных, которая создается в Oracle и используется в GIS-программном обеспечении через SDE. Один из моих коллег собирается сделать некоторые данные из этой базы данных, и я не могу найти разумный SQL-запрос для получения данных.Объединение нескольких строк в одну строку, Oracle

У меня есть две таблицы, одна с регистрациями и одна с регистрацией. Это отношения от одного до многих, поэтому регистрация может содержать одну или несколько деталей (без максимального числа).

  1. стол: Регистрация
 
RegistrationID   Date  TotLenght 
1     01.01.2010  5 
2     01.02.2010  15 
3     05.02.2009  10 

2.table: 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 

С нет rmal join Я получаю по одной строке за каждую регистрацию и детали. Кто-нибудь может мне с этим помочь? У меня нет прав администратора для базы данных, поэтому я не могу создавать таблицы или переменные. Если это возможно, я могу скопировать таблицы в Access.

+0

Это, как правило, плохая идея. Возможно, некоторые подробности о том, как вы собираетесь использовать этот выход, могут помочь кому-то предложить альтернативное решение. –

+0

Причина, по которой это не отличная идея, заключается в том, что SQL - это язык, предназначенный для реляционных баз данных, который всегда связан с отношениями и приводит к отношениям. Ваш желаемый результат не является отношением. см. http://en.wikipedia.org/wiki/Relational_model –

ответ

0

Вы не можете иметь несколько столбцов с тем же именем в одном запросе - оракул переименует их как «Date_1», «Date_2» и т. Д. Что не так с несколькими строками? Как вы к нему обращаетесь?

1

Если максимальное количество подробных записей фиксировано и известно, тогда это можно сделать. Чем больше число, тем более утомительным является запрос для кода. Вот почему Природа дала нам вырезку.

В следующем запросе используется несколько трюков. Предложение Common Table Expression (aka Sub-Query Factoring) инкапсулирует запрос в RegistrationDetail, поэтому мы можем легко ссылаться на него в нескольких местах. В подзапросе используется аналитическая функция ROW_NUMBER(), которая позволяет нам идентифицировать каждую детальную запись в группе RegistrationID. Обе эти функции были введены в Oracle 9i, поэтому они не новы, но многие люди до сих пор не знают о них.

В основном запросе используются внешние соединения для одновременного подключения таблицы регистрации к строкам в подзапросе. Он присоединяется к 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> 

Очевидно, что если у вас есть четыре Detail записей в RegistrationID вам потребуется четыре из них внешних соединений (и четыре набора столбцов в проекции).

редактировать

Я только перечитывал свой вопрос и заметил трепещут слов «Нет Максимальное число». Извините, в этом случае вам не повезло. Единственный способ решить эту проблему с переменным числом наборов - это динамический SQL, который вы фактически исключили (потому что вам нужно будет создавать дополнительные объекты схемы).

редактировать 2

Существует еще одно решение, которое только об извлечении данных и забыть макет. Oracle позволяет нам объявлять встроенные курсоры, то есть вложенные операторы select в проекции параллельно скалярам. Это передает проблему отображения вывода на клиентский инструмент.

В этой версии я использую встроенные функциональные возможности Oracle для создания вывода (на основе того, что многие инструменты могут отображать XML в эти дни). Записи RegistrationDetails представляют собой группу в XMLElement под названием REG_DETAILS, которая вложена в каждую регистрационную запись.

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 
/
+0

Спасибо за информацию. Кажется, мне удалось решить эту проблему, используя одно из ПО здесь, на работе, создав собственный отчет. Я буду держать SQL в более позднем случае! :) –

0
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, 
 
    \t wo_h.issue_date As Work_Order_IssueDate, 
 
    \t wo_h.ac_registr As WorkOrderACRegister, 
 
    \t 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
+0

Надеюсь, что этот запрос разрешит большинство проблем, так как запрос содержит условие соединения, отличное отображение данных в отношениях от одного до многих двух таблиц, такие запросы используются в генерации отчетов. – Kashif

0
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 
Смежные вопросы