这是我第一次尝试使用PIVOT。 我正在使用Microsoft SQL Server。
所以这是我的问题,我一直在阅读Pivot并且已经确定它对于将患者数据导出到格式化文件的项目非常有用,即报告,可以打印出来等等等。< / p>
VPatientPlusAllergyData是一个VIEW,它将其显示为一个样本结果,其中一些数据被删除以便于阅读
strPatientFullName strAllergy strAllergyMedication
------------------------------------------------------------
Smith, John Henry Dogs Pounces
Smith, John Henry Dogs Orange Juice
Smith, John Henry Mustard Ketchup
Smith, John Henry Mustard Sugar
这是我想要的结果
strPatientFullName strAllergy1 strAllergy1Medications strAllergy2 strAllergy2Medications
------------------------------------------------------------------------------------------------------
Smith, John Henry Dogs Pounces, OrangeJuice Mustard Ketchup, Sugar
在阅读W3Schools,观看Youtube视频甚至阅读本网站上的一些文章后,我想知道我想做的是否可能
下面是一个代码片段,但是我在IN语句中遇到了什么,当我开始质疑PIVOT的可行性是我特定问题的答案时。
GO
SELECT
strPatientFullName
,strStreetAddress
,strCity
,strState
,strZipcode
,strPrimaryPhoneNumber
,strSecondaryPhoneNumber
,blnSmoker
,decPackYears
,blnHeadOfHousehold
,dtmDateOfBirth
,strSex
,strAllergy
,strAllergyMedication
,strEmailAddress
,strRecordCreator
FROM ( SELECT * FROM VPatientPlusAllergyData ) PatientAllergyData
PIVOT
(
MAX(strAllergyMedication)
FOR strAllergy
IN ()
)
GO
希望有人更熟悉Pivot会告诉我我缺少的东西或启发我更有效的解决方案。
感谢您的帮助
******编辑:我已经决定虽然我很乐意在服务器端进行这种操作,但对于我的特定应用程序,创建大量视图然后执行SELECT查询更简单客户端并以这种方式连接它们,然后实现“导出处理”屏幕。 我很感激所有的帮助,也许有一天我会写一个脚本并让它执行服务器端,但目前这项工作还不错******
答案 0 :(得分:2)
所以为了得到你想要的东西,你实际上需要以下技术:
PIVOT
所需的列,但由于您要转动2列,因此必须PIVOT
两次或使用 条件聚合 强> 将它拉下来的主要技巧是通过连接准备你的桌子并为过敏提出一个行号。下面是一个使用公用表表达式[CTE]和STUFF()以及子选择XML来创建分隔字符串并创建行号的示例。
DECLARE @VPatientPlusAllergyData AS TABLE (strPatientFullName VARCHAR(100), strAllergy VARCHAR(50), strAllergyMedication VARCHAR(100))
INSERT INTO @VPatientPlusAllergyData VALUES
('Smith, John Henry','Dogs','Pounces')
,('Smith, John Henry','Dogs','Orange Juice')
,('Smith, John Henry','Mustard','Ketchup')
,('Smith, John Henry','Mustard','Sugar')
;WITH cte AS (
SELECT DISTINCT
v1.strPatientFullName
,v1.strAllergy
,strAllergyMedications = STUFF(
(SELECT ', ' + v2.strAllergyMedication
FROM
@VPatientPlusAllergyData v2
WHERE
v1.strPatientFullName = v2.strPatientFullName
AND v1.strAllergy = v2.strAllergy
FOR XML PATH(''))
,1,2,'')
,AllergyRowNum = DENSE_RANK() OVER (PARTITION BY v1.strPatientFullName ORDER BY v1.strAllergy)
FROM
@VPatientPlusAllergyData v1
)
SELECT
strPatientFullName
,strAllergy1 = MAX(CASE WHEN AllergyRowNum = 1 THEN strAllergy END)
,strAllergy1Medications = MAX(CASE WHEN AllergyRowNum = 1 THEN strAllergyMedications END)
,strAllergy2 = MAX(CASE WHEN AllergyRowNum = 2 THEN strAllergy END)
,strAllergy2Medications = MAX(CASE WHEN AllergyRowNum = 2 THEN strAllergyMedications END)
FROM
cte
GROUP BY
strPatientFullName
当我准备和发布这个@ZLK时写了一个很好的方法来动态地完成它。
答案 1 :(得分:1)
以下是使用STUFF语句,条件聚合和动态SQL如何执行此类操作的示例。
DECLARE @SQL NVARCHAR(MAX) = '';
SELECT @SQL += '
, MAX(CASE WHEN RN = ' + RN + ' THEN strAllergy END) strAllergy' + RN + '
, MAX(CASE WHEN RN = ' + RN + ' THEN strAllergyMedications END) strAllergyMedications' + RN
FROM (
SELECT CAST(ROW_NUMBER() OVER (PARTITION BY strPatientFullName, strAllergy ORDER BY (SELECT NULL)) AS VARCHAR(5)) RN
FROM VPatientPlusAllergyData) T
GROUP BY RN;
SELECT @SQL = 'SELECT strPatientFullName' + @SQL + '
FROM (
SELECT strPatientFullname
, strAllergy
, STUFF((SELECT '', '' + strAllergyMedication FROM VPatientPlusAllergyData WHERE strPatientFullName = T.strPatientFullName AND strAllergy = T.strAllergy FOR XML PATH ('''')), 1, 2, '''') strAllergyMedications
, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) RN
FROM VPatientPlusAllergyData T
GROUP BY strPatientFullname, strAllergy) T
GROUP BY strPatientFullname;';
PRINT @SQL;
EXEC(@SQL);
正如scsimon在评论中提到的,如果可能有任何数量的过敏,可能需要动态SQL。 stuff语句是将逗号分隔值放入单个列的一种方法。并且条件聚合的工作方式与PIVOT通常的工作方式相同,但是比普通的PIVOT语句更容易(IMO)编写和理解。