powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Как написать SELECT как бы транспонированной таблицы (UNPIVOT?)
8 сообщений из 8, страница 1 из 1
Как написать SELECT как бы транспонированной таблицы (UNPIVOT?)
    #40075136
RuCosinus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день.

Есть таблица TBLdataIN примерно вот такого вида:
FIOBirthDateMaleSalaryAmountИванов Иван Иванович1980-06-01М50000.00Петрова Петра Петровна1995-03-15Ж58000.00Сидоров Сидр Сидорович1985-09-30М52000.00
и некий ID, который прилетает в качестве входного параметра в процедуру, в которой происходит сиё действо, поэтому можно считать его константой, и принять, ну, например, за 999.

Необходимо вставить в другую таблицу TBLdataOUT (в некий шлюз) данные из TBLdataIN в следующем виде:
ROWIDFIELDNAMEFIELDVALUECONSTFIELD1999FIOИванов Иван Иванович01999BirthDate1980-06-0101999MaleМ01999SalaryAmount50000.0002999FIOПетрова Петра Петровна02999BirthDate1995-03-1502999MaleЖ02999SalaryAmount58000.0003999FIOСидоров Сидр Сидорович03999BirthDate1985-09-3003999MaleМ03999SalaryAmount52000.000

То есть строки в исходной таблице необходимо развернуть по вертикали, причем одним из значений в итоговой таблице является название поля в исходной таблице. Еще пронумеровать по количеству записей в исходной. Что-то тут столько всего, что я немного растерялся, и даже не совсем понимаю с какого боку подступиться к задаче. Направьте, будьте так любезны.

Или может плюнуть и просто сделать кучку инсертов по числу полей в исходной таблице? Там получится где-то около 20-30 инсертов. Просто хотелось бы побыстрее, за один заход это сделать. Время доступа к таблице критично.

Под спойлером положил код для тестовой исходной таблицы.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
--DROP table #TestTbl
CREATE TABLE #TestTbl(
	FIO varchar(100)
	,BirthDate date
	,Male varchar(1)
	,SalaryAmount money
) 

insert into #TestTbl
select 'Иванов Иван Иванович','19800601','М',50000
union
select 'Петрова Петра Петровна','19950315','Ж',58000
union
select 'Сидоров Сидр Сидорович','19850930','M',52000

select * from #TestTbl

...
Рейтинг: 0 / 0
Как написать SELECT как бы транспонированной таблицы (UNPIVOT?)
    #40075138
msLex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Как написать SELECT как бы транспонированной таблицы (UNPIVOT?)
    #40075145
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RuCosinus,

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
drop table if exists #TestTbl;

CREATE TABLE #TestTbl(
	FIO varchar(100)
	,BirthDate date
	,Male varchar(1)
	,SalaryAmount money
) 

insert into #TestTbl
select 'Иванов Иван Иванович','19800601','М',50000
union
select 'Петрова Петра Петровна','19950315','Ж',58000
union
select 'Сидоров Сидр Сидорович','19850930','M',52000

select
 dense_rank() over (order by b.n) as [ROW],
 999,
 c.n.value('local-name(.)', 'sysname'),
 c.n.value('.', 'varchar(max)'),
 0
from
 (select * from #TestTbl for xml raw, type) a(x) cross apply
 a.x.nodes('/row') b(n) cross apply
 b.n.nodes('./@*') c(n);
...
Рейтинг: 0 / 0
Как написать SELECT как бы транспонированной таблицы (UNPIVOT?)
    #40075150
RuCosinus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
msLex, ну я так и предполагал, что можно с помощью UNPIVOT, даже в тему вынес. Но если честно, никак он мне не дается, по MSDN-овским , да и другим примерам в интеренте, никак не ухвачу суть.

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

Еще раз спасибо всем.
...
Рейтинг: 0 / 0
Как написать SELECT как бы транспонированной таблицы (UNPIVOT?)
    #40075815
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
invm
RuCosinus,

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
drop table if exists #TestTbl;

CREATE TABLE #TestTbl(
	FIO varchar(100)
	,BirthDate date
	,Male varchar(1)
	,SalaryAmount money
) 

insert into #TestTbl
select 'Иванов Иван Иванович','19800601','М',50000
union
select 'Петрова Петра Петровна','19950315','Ж',58000
union
select 'Сидоров Сидр Сидорович','19850930','M',52000

select
 dense_rank() over (order by b.n) as [ROW],
 999,
 c.n.value('local-name(.)', 'sysname'),
 c.n.value('.', 'varchar(max)'),
 0
from
 (select * from #TestTbl for xml raw, type) a(x) cross apply
 a.x.nodes('/row') b(n) cross apply
 b.n.nodes('./@*') c(n);


Вау! Это можно сделать полностью автоматически! invm , спасибо за пример.
Мне бы и в голову не пришло, честно говоря.
Я бы руками это сделал:
Код: sql
1.
2.
3.
4.
5.
6.
7.
Select tt.* from (
select *, ROW_NUMBER() over (order by 1/0) [ROW], 999 [ID] from #TestTbl a) t
	Cross apply (Values (t.[ROW], t.[ID], 'FIO', Cast(t.FIO as sql_variant))
	,(t.[ROW], t.[ID], 'BirthDate', Cast(t.BirthDate as sql_variant))
	,(t.[ROW], t.[ID], 'Male', Cast(t.Male as sql_variant))
	,(t.[ROW], t.[ID], 'SalaryAmount', Cast(t.SalaryAmount as sql_variant))
	) tt ([ROW], [ID], [FIELDNAME],	[FIELDVALUE])


Но, кстати, на паре - тройке миллионов строк решение invm - должно сломаться, т.к. генерируемый на первом шаге xml - вылезет за 2 Гб. Ну и тормозить начнет еще раньше.
...
Рейтинг: 0 / 0
Как написать SELECT как бы транспонированной таблицы (UNPIVOT?)
    #40075823
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster
Но, кстати, на паре - тройке миллионов строк решение invm - должно сломаться, т.к. генерируемый на первом шаге xml - вылезет за 2 Гб. Ну и тормозить начнет еще раньше.
Это довольно просто решается.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
select
 dense_rank() over (order by t.rn) as [ROW],
 999,
 b.n.value('local-name(.)', 'sysname'),
 b.n.value('.', 'varchar(max)'),
 0
from
 (select *, row_number() over (order by 1/0) as rn from #TestTbl) t cross apply
 (select t.* for xml raw, type) a(x) cross apply
 a.x.nodes('/row/@*[local-name() != "rn"]') b(n);
...
Рейтинг: 0 / 0
Как написать SELECT как бы транспонированной таблицы (UNPIVOT?)
    #40075992
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
invm
uaggster
Но, кстати, на паре - тройке миллионов строк решение invm - должно сломаться, т.к. генерируемый на первом шаге xml - вылезет за 2 Гб. Ну и тормозить начнет еще раньше.
Это довольно просто решается.
(select t.* for xml raw, type) a(x) cross apply

Думаю, вот этот кусок может сломать запрос, если в исходных данных будет отбираться много записей, и размер результирующего xml превысит 2 Гб. Но это - не точно.
Наверное, можно было бы обойти этот момент, генерируя этот хмл "построчно", с привязкой к номеру строки, например.

Но всё это - не более, чем умозрительно. Сомневаюсь, что ТС собирается таким образом ворочать ~10 миллионные таблицы.
Как я уже сказал, оч. круто, спасибо.
...
Рейтинг: 0 / 0
Как написать SELECT как бы транспонированной таблицы (UNPIVOT?)
    #40076008
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster
Думаю, вот этот кусок может сломать запрос, если в исходных данных будет отбираться много записей, и размер результирующего xml превысит 2 Гб.
Тут только одна строка преобразуется в xml.
Так что вряд ли упрется в 2 Гб. Хотя умельцы найдутся всегда :)
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Как написать SELECT как бы транспонированной таблицы (UNPIVOT?)
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]