2009-06-03 2 views
14

Я работаю со столом, где есть несколько строк, которые мне нужно повернуть в столбцы. Таким образом, стержень является идеальным решением для этого и работает хорошо, когда мне нужно только одно поле. Мне нужно вернуть несколько полей, основанных на стержне. Вот псевдо-код со спецификой раздели:Несколько столбцов столбцов в T-SQL

SELECT 
    field1, 
    [1], [2], [3], [4] 
FROM 
    (
    SELECT 
    field1, 
    field2, 
    (ROW_NUMBER() OVER(PARTITION BY field1 ORDER BY field2)) RowID 
    FROM tblname 
) AS SourceTable 
PIVOT 
    (
    MAX(field2) 
    FOR RowID IN ([1], [2], [3], [4]) 
) AS PivotTable; 

выше синтаксис работает блестяще, но что мне делать, если мне нужно, чтобы получить дополнительную информацию, найденную в field3, поле 4 ....?

+2

Что именно вам нужно иметь? –

+0

Пробовал, хорошо работал для меня (3-й подход в блоге). http://dba.stackexchange.com/questions/65786/query-pivot-multiple-columns-variable-number-of-rows – JayaPrakash

ответ

11

Rewrite с помощью MAX (CASE ...) и GROUP BY:

select 
    field1 
, [1] = max(case when RowID = 1 then field2 end) 
, [2] = max(case when RowID = 2 then field2 end) 
, [3] = max(case when RowID = 3 then field2 end) 
, [4] = max(case when RowID = 4 then field2 end) 
from (
    select 
    field1 
    , field2 
    , RowID = row_number() over (partition by field1 order by field2) 
    from tblname 
) SourceTable 
group by 
    field1 

Оттуда вы можете добавить в field3, поле 4 и т.д.

+0

То, что я закончил, заключалось в использовании операторов CASe в CTE для заполнения этой производной таблицы, к которой я присоединился с дополнительными критериями. Вот КТР: – websch01ar

+0

С cteSec, как ( \t ВЫБРАТЬ \t vSec.ID, \t --Secretary 1 ----------------------- - \t MAX ( \t \t ПРИМЕР vSec.RowID \t \t КОГДА 1 ТОГДА vSec.field1 \t \t ИНАЧЕ '' \t \t \t КОНЕЦ ) [SEC_OfficePhone1], \t MAX ( \t \t CASE vSec.RowID \t \t WHEN 1 THEN vSec.поле2 \t \t ИНАЧЕ '' \t \t \t КОНЕЦ ) [SEC_OfficeFax1], \t \t ОТ \t ( \t --THIS будет внутренний запрос (он назначает строк секретарей) \t Выбор TOP 100 процентов \t \t поле1, поле2, ID \t \t (ROW_NUMBER() OVER (PARTITION BY vs.ID ORDER BY vs.ID2)) RowId \t ОТ tblname против \t ORDER BY vs.ID, ID2 \t) Vsec \t GROUP BY \t vSec.ID ) – websch01ar

+0

Итак, с помощью этого метода я жёстко число столбцов я ожидал. Обычно я предпочитаю делать это динамически, так как он обязательно изменится. Но, как компания, мы фокусируемся на сокращении накладных расходов, поэтому я не вижу необходимости в более чем четырех секретарях на одного босса ... Я даю вам кредит, потому что ваш пост привел меня по дороге, чтобы написать 20 случаев заявления. Это работает как прелесть с суб-вторым ответом. – websch01ar

1

Я не уверен, что вы используете MS SQL Server, но если вы ... Возможно, вы захотите взглянуть на функциональность CROSS APPLY. В основном это позволит вам применить результаты табличного значения UDF к набору результатов. Это потребует, чтобы вы поставили свой сводный запрос в набор результатов с табличным значением.

http://weblogs.sqlteam.com/jeffs/archive/2007/10/18/sql-server-cross-apply.aspx

+0

-1 Не вижу связи с вопросом – Andomar

+0

Вопрос помечен как T-SQL , Это диалект MS ... – RolandTumble

+0

Это также диалект на Sybase. –

1

обернуть SQL заявление с что-то вроде:

select a.segment, sum(field2), sum(field3) 
from (original select with case arguments) a 
group by a.segment 

Он должен сворачивать ваши результаты в один ряд, сгруппированы по полю1.

1

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

-- populate some test data 
if object_id('tempdb..#tmp') is not null drop table #tmp 
create table #tmp (
    ID int identity(1,1) not null, 
    MainField varchar(100), 
    ThatField int, 
    ThatOtherField datetime 
) 

insert into #tmp (MainField, ThatField, ThatOtherField) 
select 'A', 10, '1/1/2000' union all 
select 'A', 20, '2/1/2000' union all 
select 'A', 30, '3/1/2000' union all 
select 'B', 10, '1/1/2001' union all 
select 'B', 20, '2/1/2001' union all 
select 'B', 30, '3/1/2001' union all 
select 'B', 40, '4/1/2001' union all 
select 'C', 10, '1/1/2002' union all 
select 'D', 10, '1/1/2000' union all 
select 'D', 20, '2/1/2000' --union all 

-- pivot over multiple columns using the 1.1, 1.2, 2.1, 2.2 sequence trick 
select 
    MainField, 
    max([1.1]) as ThatField1, 
    max([1.2]) as ThatOtherField1, 
    max([2.1]) as ThatField2, 
    max([2.2]) as ThatOtherField2, 
    max([3.1]) as ThatField3, 
    max([3.2]) as ThatOtherField3, 
    max([4.1]) as ThatField4, 
    max([4.2]) as ThatOtherField4 
from 
    (
     select x.*, 
      cast(row_number() over (partition by MainField order by ThatField) as varchar(2)) + '.1' as ThatFieldSequence, 
      cast(row_number() over (partition by MainField order by ThatField) as varchar(2)) + '.2' as ThatOtherFieldSequence 
     from #tmp x 
    ) a 
    pivot (
     max(ThatField) for ThatFieldSequence in ([1.1], [2.1], [3.1], [4.1]) 
    ) p1 
    pivot (
     max(ThatOtherField) for ThatOtherFieldSequence in ([1.2], [2.2], [3.2], [4.2]) 
    ) p2 
group by 
    MainField 
Смежные вопросы