2013-12-16 2 views
1

У меня есть следующая таблица с данными: (?)Поворотная без известного имени столбца

A B 
=== === 
M 2 
M 3 
M 5 
N 5 
N 2 
O 6 
P 13 
P 7 
P 9 
P 11 
P 3 

Теперь мне нужен PIVOT запрос к:

  • группы по колонке А.
  • Сортировать по колонка B.
  • Возьмите наименьшие 3 значения из столбца B.
  • Поместите эти значения в новые столбцы B1, B2, B3

Так что результат будет:

A B1 B2 B3 
=== ==== ==== ==== 
M 2 3 5 
N 2 5 null 
O 6 null null 
P 3 7 9 

До сих пор я пытался создавать запросы с TOP, GROUP BY, PIVOT. Я думаю, что лучший способ пойти с PIVOT, но поскольку у меня нет значения, которое я могу использовать в качестве имени столбца, я застрял. Кроме того, сделать выбор из 3-х из этих значений также довольно сложно.

* EDIT *

Их уникальное ограничение на колонках А и В, так что значения для B всегда уникальны для того же А.

+0

В какой базе данных вы используете? Oracle или SQL Server? –

+0

Я использую Oracle. Я удалил неправильный тег. –

+1

@MartinMulder Какую версию Oracle вы используете? – Taryn

ответ

4

Вот такой подход, который работает как с Oracle и SQL Server (исходный вопрос был помечен обеими базами данных).

Вы можете просто перечислить b значения для каждого a с помощью dense_rank() (или row_number(), но dense_rank() даст три различных значения, если есть дубликаты). Затем стержень с помощью условной агрегации:

with ab as (
     select a, b, 
      dense_rank() over (partition by a order by b asc) as seqnum 
     from t 
    ) 
select a, 
     max(case when seqnum = 1 then b end) as b1, 
     max(case when seqnum = 2 then b end) as b2, 
     max(case when seqnum = 3 then b end) as b3 
from ab 
group by a; 

EDIT:

Вопрос остается неясным, что делать, если есть дубликаты. Например, если данные в b составляют 1, 1, 2, 3. Какими должны быть три столбца?

1, 2, 3 

или 1, 1, 2

Применение dense_rank() помещает три разные значения в столбцы (первый возможный результат). Использование row_number() поставит три наименьших значения (второй результат). Если никогда не было повторяющихся значений, то dense_rank() и row_number() дают одинаковые результаты.

+0

'DENSE_RANK' не работает таким образом (по крайней мере, в SQL Server), он даст такое же значение, если есть дубликаты. 'ROW_NUMBER' с другой стороны ведет себя так, как вы хотите – Lamak

+0

@Lamak. , , Я имел в виду, что 'dense_rank()' будет давать три разных значения 'b', если есть дубликаты. 'row_number()' будет повторять значения 'b'. Неясно, чего хочет OP. –

+0

Да, и это то, что я говорю, это неправильно, 'dense_rank' вернет одно и то же значение в случае дубликата, а' row_number' не будет – Lamak

7

Вы можете использовать функцию PIVOT для получения результата, но я бы также реализовал функцию окна, похожую на row_number(), чтобы получить окончательный результат. Функция row_number() создаст уникальный порядковый номер для каждого значения B, если вы разделите данные по столбцу A. Эта последовательность номер будет использоваться в качестве новых имен столбцов:

select a, B1, B2, B3 
from 
(
    select a, b, 
    row_number() over(partition by a 
         order by b) seq 
    from yourtable 
) d 
pivot 
(
    max(b) 
    for seq in ('1' as B1, '2' as B2, '3' as B3) 
) piv; 

См SQL Fiddle with Demo. Это даст результаты:

| A | B1 |  B2 |  B3 | 
|---|----|--------|--------| 
| M | 2 |  3 |  5 | 
| N | 2 |  5 | (null) | 
| O | 6 | (null) | (null) | 
| P | 3 |  7 |  9 | 
Смежные вопросы