Oracle SQL - преобразование значений столбцов из N строк в N столбцов в 1 строке - PullRequest
0 голосов
/ 17 февраля 2012

Уловка с этим по сравнению с другими вопросами (например, «Oracle конвертирует строки в столбцы») заключается в том, что значения моих столбцов являются произвольными строками, а не тем, что я могу использовать с декодированием. Возьмите этот запрос:

Таблица описаний здесь отображает имена людей в описания, но у каждого человека может быть несколько описаний, например. "носит шляпу" или "высок".

Select firstName, lastName, 
(Select description from descriptions --This can return any number of rows (0 or more)
 where description.firstName = people.firstName
 and description.lastName = people.lastName
 and rownum <= 3)
from people
where age >= 25;

Я бы хотел вывод, подобный этому:

FIRSTNAME LASTNAME DESCRIPTION1 DESCRIPTION2 DESCRIPTION3
Jeremy    Smith    Tall         Confused        (null)
Anne      Smith    (Null)       (Null)          (Null)
Mark      Davis    Short        Smart           Strong

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

Я использую Oracle 11.1. Можно ли это сделать эффективно?

Ответы [ 2 ]

2 голосов
/ 17 февраля 2012

Предполагая, что вам все равно, в каком порядке возвращаются описания (т. Е. У Джереми Смита также могут быть Description1 или "Confused" и Description2 "Tall"), вам просто нужно повернутьна номер строки.Если вы заботитесь о порядке, в котором возвращаются описания, вы можете добавить предложение ORDER BY к оконной функции в аналитической функции ROW_NUMBER

SELECT firstName, 
       lastName,
       MAX( CASE WHEN rn = 1 THEN description ELSE NULL END ) description1,
       MAX( CASE WHEN rn = 2 THEN description ELSE NULL END ) description2,
       MAX( CASE WHEN rn = 3 THEN description ELSE NULL END ) description3
  FROM (SELECT firstName,
               lastName,
               description,
               row_number() over (partition by lastName, firstName) rn
          FROM descriptions
               JOIN people USING (firstName, lastName)
         WHERE age >= 25)
   GROUP BY firstname, lastname

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

0 голосов
/ 31 июля 2012

Я попробовал эту опцию, но она говорит, что мы должны отдать заказ по предложению внутри функции анализа строк, как показано ниже,

row_number() over (partition by lastName, firstName order by lastName, firstName) rn

Это прекрасно работает для моего сценария, когда я помещаю заказ по предложению.*

Мой сценарий состоит в том, что данные пользователя находятся в таблице A, группы пользователей - в таблице C, а связь между пользователями и группами пользователей - в таблице B. Один пользователь может иметь несколько групп пользователей.Мне нужно получить результаты с именем пользователя с несколькими группами пользователей в одной строке

**

Запрос:

**

SELECT username,
MAX( CASE WHEN rn = 1 THEN ugroup ELSE NULL END ) usergroup1,
MAX( CASE WHEN rn = 2 THEN ugroup ELSE NULL END ) usergroup2,
MAX( CASE WHEN rn = 3 THEN ugroup ELSE NULL END ) usergroup3, 
MAX( CASE WHEN rn = 4 THEN ugroup ELSE NULL END ) usergroup4,
MAX( CASE WHEN rn = 5 THEN ugroup ELSE NULL END ) usergroup5,
from (
select 
a.user_name username, 
c.name ugroup,
row_number() over (partition by a.user_name order by a.user_name) rn
from users a,
usergroupmembership b,
usergroups c
where a.USER_NAME in ('aegreen',
'esportspau'
)
and a.user_id= b.user_id
and b.group_id=c.group_id
)group by uname;

**

Результат запроса

**

USERNAME    USERGROUP1  USERGROUP2  USERGROUP3  USERGROUP4  USERGROUP5
aegreen US_GOLF (null)  (null)  (null)  (null)
esportspau  EMEA - FSERVICE USER_ES_ES  EMEA-CR-ONLY    (null)  (null)
...