Несколько столбцов столбцов в 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;
Вышеупомянутый синтаксис работает блестяще, но что мне делать, когда мне нужно получить дополнительную информацию, найденную в поле3, поле4....?
Ответы
Ответ 1
Перепишите с помощью 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
Оттуда вы можете добавить в поле3, поле4 и т.д.
Ответ 2
Я не уверен, что вы используете MS SQL Server, но если вы... Возможно, вы захотите взглянуть на функциональность CROSS APPLY для этого движка. В основном это позволит вам применить результаты табличного значения UDF к набору результатов. Это потребовало бы, чтобы вы поставили свой сводный запрос в набор значений с табличным значением.
http://weblogs.sqlteam.com/jeffs/archive/2007/10/18/sql-server-cross-apply.aspx
Ответ 3
заверните свой оператор sql чем-то вроде:
select a.segment, sum(field2), sum(field3)
from (original select with case arguments) a
group by a.segment
Он должен свернуть ваши результаты в одну строку, сгруппированную по полю1.
Ответ 4
Трюк для выполнения нескольких опорных точек над 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
Ответ 5
Можно развернуть несколько столбцов, но вам нужно быть осторожным при повторном использовании столбца поворота на нескольких опорных точках. Вот хороший пост в блоге по теме:
http://pratchev.blogspot.com/2009/01/pivoting-on-multiple-columns.html