使用Pivot和非数字数据

时间:2016-11-10 21:39:52

标签: sql sql-server pivot

这是我第一次尝试使用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查询更简单客户端并以这种方式连接它们,然后实现“导出处理”屏幕。 我很感激所有的帮助,也许有一天我会写一个脚本并让它执行服务器端,但目前这项工作还不错******

2 个答案:

答案 0 :(得分:2)

所以为了得到你想要的东西,你实际上需要以下技术:

  • 对于strAllergyMedications,您需要 将行连接到分隔字符串
  • 然后,要将您的行设置为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)编写和理解。