Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Как да трансформирате данни от редове въз основа на конкретна колона в друга структура от данни

Можете да използвате unpivot/pivot, за да получите резултата, който искате. Има няколко различни начина, по които можете да получите резултата, ако имате ограничен брой стойности, тогава можете да кодирате твърдо заявката, но ако имате неизвестен брой стойности, тогава ще трябва да използвате динамичен SQL.

Процесът UNPIVOT ще конвертира множеството колони на c1 , и т.н.` в няколко реда. След като данните са в множеството редове, можете лесно да приложите функцията PIVOT. Можете да използвате функцията unpivot или CROSS APPLY, за да конвертирате данните от множество колони:

изберете id, col ='Service'+Service+'_'+col+'_'+cast(seq as varchar(10)), valuefrom( select id, service, c1, cn, row_number() over (разделяне по id подреждане по услуга) seq от вашата таблица) tcross apply( изберете 'c1', c1 съюз всички изберете 'cn', cn) c (col, value) 

Вижте SQL Fiddle с демонстрация . Кръстосаното прилагане ще преобразува вашите данни във формат:

<предварителен код>| ID | COL | СТОЙНОСТ || 1 | УслугаA_c1_1 | 5 || 1 | УслугаA_cn_1 | 3 || 1 | УслугаB_c1_2 | 2 || 1 | УслугаB_cn_2 | 1 || 2 | УслугаA_c1_1 | 9 || 2 | УслугаA_cn_1 | 4 |

След като данните са в този формат, можете да приложите PIVOT:

изберете id, ServiceA_c1_1, ServiceA_cn_1, ServiceB_c1_2, ServiceB_cn_2from( изберете id, col ='Service'+Service+'_'+col+'_'+cast(seq като varchar(10)), стойност от ( изберете id, service, c1, cn, row_number() over(partition by id order by service) seq from yourtable ) t cross apply ( select 'c1', c1 union all select 'cn', cn ) c (col, value)) dpivot( max(стойност) за колона в (ServiceA_c1_1, ServiceA_cn_1, ServiceB_c1_2, ServiceB_cn_2)) piv; 

Вижте SQL Fiddle с демонстрация .

След това, ако имате неизвестен брой стойности, можете да конвертирате горната заявка в динамичен SQL:

DECLARE @cols AS NVARCHAR(MAX), @query AS NVARCHAR(MAX)select @cols =STUFF((SELECT ',' + QUOTENAME('Service'+Service+'_'+col+'_'+ cast(seq as varchar(10))) from ( select service, row_number() over(partition by id order by service) seq from yourtable )d cross apply ( select 'c1', 1 union all select 'cn', 2 ) c (col, so) group by seq, Service, col, so order by seq, so FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,' ')set @query ='SELECT id, ' + @cols + ' from ( select id, col =''Service''+Service+''_''+col+''_''+cast(seq as varchar(10) )), стойност от (изберете id, service, c1, cn, row_number() over(partition by id order by service) seq from yourtable ) t cross apply ( select ''c1'', c1 union all select ''cn'', cn ) c (col, value) ) x pivot ( max(value) for col in (' + @cols + ') ) p 'execute sp_executesql @query; 

Вижте SQL Fiddle с демонстрация . И двете ще дадат резултат:

<предварителен код>| ID | SERVICEA_C1_1 | SERVICEA_CN_1 | SERVICEB_C1_2 | SERVICEB_CN_2 || 1 | 5 | 3 | 2 | 1 || 2 | 9 | 4 | (нула) | (null) |


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Изявление за Sql Case в Sql IN

  2. Проектиране на релации 1:1 и 1:m в SQL Server

  3. Как да промените режима на оторизация на SQL Server без Management Studio

  4. Как една SQL заявка може да има две клаузи from?

  5. 2 начина за връщане на името на сървъра в SQL Server (T-SQL)