SQL Server 行列转换

一 行转列

1多行转成一列(并以","隔开)

SELECT  name ,
        value = ( STUFF(( SELECT    ',' + value
                          FROM      A
                          WHERE     name = Test.name
                        FOR
                          XML PATH('')
                        ), 1, 1, '') )
FROM    A AS Test
GROUP BY name;
PS:STUFF语句就是为了去掉第一个【逗号】

附STUFF用法:(从原字符的第二个开始共三个字符替换为后面的字符)
SELECT STUFF('abcdef', 2, 3, 'ijklmn'); 


SQL Server 2000静态SQL通过group by 、max语句进行行转列静态SQL

select a.MemberId,a.Age,a.Gender,a.ColorectalCancerFamilyHistory,a.ProstateCancerFamilyHistory,

max(CASE a.Conidtion WHEN 'Colorectal Cancer' THEN a.RiskScore ELSE '' end) ColorectalCancerRiskScore,
max(CASE a.Conidtion WHEN 'Colorectal Cancer' THEN a.RiskLevel ELSE '' end) ColorectalCancerRiskLevel,
max(CASE a.Conidtion WHEN 'Prostate Cancer' THEN a.RiskScore ELSE '' end) ProstateCancerIPSSScore,
max(CASE a.Conidtion WHEN 'Prostate Cancer' THEN a.RiskLevel ELSE '' end) ProstateCancerRiskLevel,
max(CASE a.Conidtion WHEN 'Diabetes Mellitus' THEN a.RiskLevel ELSE '' end) DiabetesMellitusRiskLevel,
max(CASE a.Conidtion WHEN 'Breast Cancer' THEN a.RiskScore ELSE '' end) BreastCancerAbsoluteRisk,
max(CASE a.Conidtion WHEN 'Breast Cancer' THEN a.RiskLevel ELSE '' end) BreastCancerRiskLevel,
max(CASE a.Conidtion WHEN 'Heart Disease/Stroke' THEN a.RiskScore ELSE '' end) CardiovascularDiseaseRiskScore,
max(CASE a.Conidtion WHEN 'Heart Disease/Stroke' THEN a.RiskLevel ELSE '' end) CardiovascularDiseaseRiskLevel,
max(CASE a.Conidtion WHEN 'Blood pressure' THEN a.RiskLevel ELSE '' end) BloodPressureRiskLevel,
max(CASE a.Conidtion WHEN 'Body Mass Index' THEN a.RiskLevel ELSE '' end) BodyMassIndexRiskLevel,
max(CASE a.Conidtion WHEN 'Cholesterol' THEN a.RiskLevel ELSE '' end) BloodLipidCholesterolRiskLevel,
max(CASE a.Conidtion WHEN 'Mental Health' THEN a.RiskLevel ELSE '' end) MentalHealthRiskLevel
from 
	(select tc.member_id MemberId,
		SUBSTRING(ti.informationjson, CHARINDEX('"age":', ti.informationjson) + LEN('"age":'),
						  CHARINDEX(',"gender"', ti.informationjson) - CHARINDEX('"age":', ti.informationjson)
						  - LEN('"age":'))Age,
		SUBSTRING(ti.informationjson, CHARINDEX('"gender":"', ti.informationjson) + LEN('"gender":"'),
					  CHARINDEX('","from"', ti.informationjson) - CHARINDEX('"gender":"', ti.informationjson)
					  - LEN('"gender":"')) Gender,
		case SUBSTRING(ti.informationjson, CHARINDEX('"colCancer":"', ti.informationjson) + LEN('"colCancer":"'),
					  CHARINDEX('","diaMell"', ti.informationjson) - CHARINDEX('"colCancer":"', ti.informationjson)
					  - LEN('"colCancer":"'))  when 'A' then 'Yes' when 'B' then 'No' else 'NA' end ColorectalCancerFamilyHistory,
		case SUBSTRING(ti.informationjson, CHARINDEX('"pc":"', ti.informationjson) + LEN('"pc":"'),
					  CHARINDEX('","oc"', ti.informationjson) - CHARINDEX('"pc":"', ti.informationjson)
					  - LEN('"pc":"')) when 'A' then 'Yes' when 'B' then 'No' else 'NA' end  ProstateCancerFamilyHistory,
		tc.condition Conidtion,
		case tc.result when 'A' then 'Yes' when 'B' then 'NA' else replace(replace(tc.result,'<','<'),'>','>') end RiskScore,
		tc.interpretation RiskLevel
		from twh_calculate_result tc,twh_online_survey_information ti,twh_user tu where tc.member_id=ti.member_id and tc.member_id=tu.member_id and tu.clntcode='16163') a
group by a.MemberId,a.Age,a.Gender,a.ColorectalCancerFamilyHistory,a.ProstateCancerFamilyHistory

order by a.MemberId asc

3、使用SQL Server 2005静态SQL

SELECT  *
FROM    tb PIVOT( MAX(分数) FOR 课程 IN ( 语文, 数学, 物理 ) ) a;

4、使用SQL Server 2005动态SQL

--使用stuff()

DECLARE @sql VARCHAR(8000)

SET @sql=''  --初始化变量@sql

SELECT @sql=@sql+','+课程 FROM tb GROUP BY 课程 --变量多值赋值

SET @sql=stuff(@sql,1,1,'')--去掉首个','

SET @sql='select * from tb pivot (max(分数) for 课程 in ('+@sql+'))a'

exec(@sql)

 

--或使用isnull()

DECLARE @sql VARCHAR(8000)


SELECT @sql=isnull(@sql+',','')+课程 FROM tb GROUP BY 课程           

SET @sql='select * from tb pivot (max(分数) for 课程 in ('+@sql+'))a'

exec(@sql)

二 行转列

1、建立表格

IF OBJECT_ID('tb')IS NOT NULL DROP TABLE tb

go

CREATE TABLE tb(姓名 VARCHAR(10),语文 INT,数学 INT,物理 INT)

INSERT INTO tb VALUES('张三',74,83,93)

INSERT INTO tb VALUES('李四',74,84,94)

go

SELECT * FROM tb

go

2、使用SQL Server 2000静态SQL

--SQL SERVER 2000静态SQL。

SELECT * FROM

(

 SELECT 姓名,课程='语文',分数=语文 FROM tb

 UNION ALL

 SELECT 姓名,课程='数学',分数=数学 FROM tb

 UNION ALL

 SELECT 姓名,课程='物理',分数=物理 FROM tb

) t

ORDER BY 姓名,CASE 课程 WHEN '语文' THEN 1 WHEN '数学' THEN 2 WHEN '物理' THEN 3 end

SQL Server 行列转换_第1张图片

2、使用SQL Server 2000动态SQL

--SQL SERVER 2000动态SQL。

--调用系统表动态生态。

DECLARE @sql VARCHAR(8000)

SELECT @sql=isnull(@sql+' union all ','')+' select 姓名, [课程]='

+quotename(Name,'''')+' , [分数] = '+quotename(Name)+' from tb'

FROM syscolumns

WHERE Name!='姓名' AND ID=object_id('tb')--表名tb,不包含列名为姓名的其他列

ORDER BY colid

exec(@sql+' order by 姓名')

go

3、使用SQL Server 2005静态SQL

--SQL SERVER 2005动态SQL

SELECT 姓名,课程,分数 FROM tb unpivot (分数 FOR 课程 IN([语文],[数学],[物理])) t

4、使用SQL Server 2005动态SQL

--SQL SERVER 2005动态SQL

DECLARE @sql NVARCHAR(4000)

SELECT @sql=isnull(@sql+',','')+quotename(Name)

FROM syscolumns

WHERE ID=object_id('tb')AND Name NOT IN('姓名')

ORDER BY Colid

SET @sql='select 姓名,[课程],[分数] from tb unpivot ([分数] for [课程] in('+@sql+'))b'

exec(@sql)


你可能感兴趣的:(SQL Server 行列转换)