Объединить две строки в одном столбце в одну строку (Oracle); использовать LISTAGG?

Я использую Oracle в Hyperion Studio. Я считаю, что это Oracle 11, но я не знаю, как проверить ... это все для меня в новинку, и я очень, очень новичок, прошу прощения.

В любом случае я использую запрос, чтобы вернуть список классов вместе с именами преподавателей, которые их преподают.

Возникают две проблемы:

  1. Имя инструктора разбито на несколько столбцов. Я легко решил эту проблему с помощью рекурсивного CONCAT в вычисляемом элементе:

    CONCAT (Request.Instructor_Last_Name,CONCAT(', ',Request.Instructor_First_Name))
    
  2. Курс может иметь более одного инструктора. Я хочу, чтобы у каждого курса была только одна строка в результатах, поэтому я решил, что попытаюсь показать всех инструкторов в одном объединенном поле.

Чтобы попытаться решить вторую проблему, я попытался использовать LISTAGG и CONCAT вместе в вычисляемом элементе:

LISTAGG(CONCAT (Request.Instructor_Last_Name,CONCAT(', ',Request.Instructor_First_Name)), 'and ') 
WITHIN GROUP (ORDER BY Request.Instructor_Last_Name DESC) "All Instructors"

Это возвращает ошибку ORA-00937: not a single-group group function.

Это привело меня к следующему вопросу: LISTAGG Query ORA-00937 : не функция одногрупповой группы Я пробовал варианты решения там, но безуспешно. Вот один пример, который я попытался:

LISTAGG(CONCAT (Request.Instructor_Last_Name,CONCAT(', ',Request.Instructor_First_Name)), 'and ') 
WITHIN GROUP (ORDER BY Request.Instructor_Last_Name DESC) "All Instructors"
FROM Request
GROUP BY *

Это возвращает ошибку:

ORA-00936: отсутствует выражение

Я тоже пробовал заменить

LISTAGG(CONCAT (Request.Instructor_Last_Name,CONCAT(', ',Request.Instructor_First_Name)), 'and ') 

с участием

LISTAGG(Request.Instructor_Last_Name || ', ' || Request.Instructor_First_Name,'and ') 

на основе чего-то еще, что я читал, но это, похоже, не имело никакого значения (я даже не уверен, что это сработает в любом случае).

Это меня утомило. Я уверен, что на данный момент ответ, должно быть, ускользает от меня только из-за моей неопытности, поэтому любая помощь очень ценится ...


Вот очень урезанная версия запроса с использованием предложенного кода vkp (это баннеры, как некоторые могут узнать):

SELECT DISTINCT 
AL1.SFRSTCR_TERM_CODE, AL1.SFRSTCR_CRN, 
AL3.SPRIDEN_FIRST_NAME, AL3.SPRIDEN_LAST_NAME, 
CONCAT ((AL3.SPRIDEN_LAST_NAME),CONCAT(', ',(AL3.SPRIDEN_FIRST_NAME))),   
select Student_Registration_CRN,
LISTAGG((Instructor_Last_Name||', '||Instructor_First_Name), 'and '))
WITHIN GROUP (ORDER BY Instructor_Last_Name DESC) "All Instructors"
FROM Request
group by Student_Registration_CRN 
FROM SATURN.SFRSTCR AL1, SATURN.SIRASGN AL2, SATURN.SPRIDEN AL3 
WHERE ( AL1.SFRSTCR_TERM_CODE = AL2.SIRASGN_TERM_CODE (+) 
AND  AL1.SFRSTCR_CRN = AL2.SIRASGN_CRN (+) 
AND  AL2.SIRASGN_PIDM = AL3.SPRIDEN_PIDM (+))  
AND ((AL3.SPRIDEN_CHANGE_IND IS NULL AND AL1.SFRSTCR_TERM_CODE='201660'))

Это вызывает ошибку:

ORA-00936: отсутствует выражение

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


Я пробовал использовать SQL, предложенный Boneist, напрямую импортировав файл .SQL, а не используя визуальный конструктор и вычисляемые элементы. Вот что я пытался запустить:

select distinct
   al1.sfrstcr_term_code,
   al1.sfrstcr_crn,
   al3.spriden_first_name,
   al3.spriden_last_name,
   al3.spriden_last_name||', '||al3.spriden_first_name,
   (select   sfrstcr_crn,
             listagg(spriden_last_name || ', ' || spriden_first_name, 'and ')
               within group (order by spriden_last_name desc)
    from     request req
    where    sfrstcr_crn = al1.sfrstcr_crn
    group by sfrstcr_crn) "All Instructors"
from   saturn.sfrstcr al1
   left outer join saturn.sirasgn al2 on (al1.sfrstcr_term_code = al2.sirasgn_term_code
                                          and al1.sfrstcr_crn = al2.sirasgn_crn)
   left outer join saturn.spriden al3 on (al2.sirasgn_pidm = al3.spriden_pidm(+))
where  al3.spriden_change_ind is null
and    al1.sfrstcr_term_code = '201660';

К сожалению, это возвращает ошибку:

ORA-00933: Команда SQL не завершена должным образом

Я подумал, основываясь на некотором поиске, что могло быть так, что кавычки не импортировались правильно, поэтому я попробовал кое-что еще более простое:

select distinct
   al1.sfrstcr_term_code,
   al1.sfrstcr_crn,
   al3.spriden_first_name,
   al3.spriden_last_name
from   saturn.sfrstcr al1
   left outer join saturn.sirasgn al2 on (al1.sfrstcr_term_code = al2.sirasgn_term_code
                                          and al1.sfrstcr_crn = al2.sirasgn_crn)
   left outer join saturn.spriden al3 on (al2.sirasgn_pidm = al3.spriden_pidm(+))
where  al3.spriden_change_ind is null;

Но я все равно получаю ту же ошибку ... ???? Я попытался найти, что еще могло ее вызвать, но не нашел ничего полезного ... Я не уверен, что еще попробовать на этом этапе.


person Community    schedule 18.05.2016    source источник
comment
group by *? что это должно делать?   -  person Vamsi Prabhala    schedule 18.05.2016
comment
Где-то в процессе поиска я читал, что вам нужно сгруппировать по тому, что было выбрано, и я не был уверен, что именно выбирает вычисляемый элемент, поэтому я подумал, что попробую просто сгруппировать по чему угодно ... что, похоже, не сработало , ой ...   -  person    schedule 18.05.2016


Ответы (3)


Попробуй это.

select class_id,
LISTAGG((Instructor_Last_Name||', '||Instructor_First_Name), 'and '))
WITHIN GROUP (ORDER BY Instructor_Last_Name DESC) "All Instructors"
FROM Request
group by class_id
person Vamsi Prabhala    schedule 18.05.2016
comment
Заменив class_id на соответствующее имя столбца (это Student_Registration_CRN, извините, что пропустил!), Я попробовал это, но, к сожалению, получил ошибку _1 _... - person ; 18.05.2016
comment
вы можете опубликовать полный используемый запрос? - person Vamsi Prabhala; 18.05.2016
comment
Конечно ... это немного сложно, так как ссылается на несколько таблиц, но я добавлю его выше ... - person ; 18.05.2016
comment
Я только что добавил урезанную версию выше. Я должен отойти на время, поэтому извиняюсь, если не отвечу сразу же! - person ; 18.05.2016

Похоже, CONCAT не нужен?

http://nimishgarg.blogspot.in/2010/02/oracle-new-string-aggregation.html

person Rob Wood    schedule 18.05.2016

Я думаю, вам нужно что-то вроде:

with sample_data as (select 'Bob' first_name, 'Jones' last_name, 1 course_id from dual union all
                     select 'John' first_name, 'Bloggs' last_name, 1 course_id from dual union all
                     select 'Fred' first_name, 'Hoskins' last_name, 1 course_id from dual union all
                     select 'Bob' first_name, 'Jones' last_name, 2 course_id from dual union all
                     select 'John' first_name, 'Bloggs' last_name, 2 course_id from dual union all
                     select 'Fred' first_name, 'Hoskins' last_name, 3 course_id from dual)
-- end of setting up a subquery to mimic a table called sample_data for use in the SQL below:
select course_id,
       listagg(first_name||' '||last_name, ', ') within group (order by last_name) instructors
from   sample_data
group by course_id;


 COURSE_ID INSTRUCTORS                             
---------- ----------------------------------------
         1 John Bloggs, Fred Hoskins, Bob Jones    
         2 John Bloggs, Bob Jones                  
         3 Fred Hoskins         

Обратите внимание, как я заменил ваши CONCAT на ||, так как это гораздо более гибко и не требует вложенности CONCAT, если вы соединяете более двух строк вместе! Его также намного легче читать.


Я подозреваю, что запрос, который вы ищете, похож на:

select distinct
       al1.sfrstcr_term_code,
       al1.sfrstcr_crn,
       al3.spriden_first_name,
       al3.spriden_last_name,
       al3.spriden_last_name||', '||al3.spriden_first_name,
       (select   student_registration_crn,
                 listagg(instructor_last_name || ', ' || instructor_first_name, 'and ')
                   within group (order by instructor_last_name desc)
        from     request req
        where    <join condition(s) between this query and the main query>
        group by student_registration_crn) "All Instructors"
from   saturn.sfrstcr al1
       left outer join saturn.sirasgn al2 on (al1.sfrstcr_term_code = al2.sirasgn_term_code
                                              and al1.sfrstcr_crn = al2.sirasgn_crn)
       left outer join saturn.spriden al3 on (al2.sirasgn_pidm = al3.spriden_pidm(+))
where  al3.spriden_change_ind is null
and    al1.sfrstcr_term_code = '201660';

Я исправил некоторые проблемы с вашим запросом:

  1. Скалярный подзапрос (когда вы заполняете столбец с помощью оператора select) необходимо заключить в квадратные скобки.
  2. По возможности используйте новые соединения в стиле ANSI, а не соединения в старом стиле.
  3. Вам не хватает условия соединения из вашего скалярного подзапроса во внешний запрос - вам необходимо включить их. Кроме того, скалярный подзапрос должен возвращать не более одной строки, иначе вы получите ошибку.
person Boneist    schedule 18.05.2016
comment
Как и в случае с ответом vkp, я попробовал это, заменив соответствующие имена полей, но получил ошибку ORA-00936: missing expression. Я помещаю этот код как вычисляемый элемент. Может ли это иметь какое-то отношение к этому? - person ; 18.05.2016
comment
@Violet Я обновил свой ответ некоторыми указателями на ваш урезанный запрос. Надеюсь, это поможет! - person Boneist; 19.05.2016
comment
Спасибо! SQL (кроме подзапроса) был автоматически сгенерирован Hyperion Studio, но я только что обнаружил, что можно импортировать собственный SQL, поэтому я попытался это сделать. Я добавил свои результаты к своему первоначальному вопросу. - person ; 19.05.2016