SQL - 根据值创建多个列

时间:2015-02-06 18:01:51

标签: sql sql-server-2008 replace case

我之前从未发布

  1. 这里的SQL新手
  2. 我希望格式化正确
  3. 我一直试图找到一种方法来操纵这些数据,但还没有找到我认为符合我需要的东西。我需要根据另一列的值创建其他列(在我的情况下,基于观察列)

    PID | Observation_Date | Observation_Time | Obs_Value | Observation
    
    1424285941000610    | 20050603  | 115459    | 110   mm Hg   |BP Systolic  
    1424285941000610    | 20050603  | 115459    | 80    mm Hg   |BP Diastolic  
    1424285941000610    | 20050603  | 115459    | N             |Smoking Status  
    1424285941000610    | 20050912  | 141308    | 110   mm Hg   |BP Systolic  
    1424285941000610    | 20050912  | 141308    | 86    mm Hg   |BP Diastolic  
    1424285941000610    | 20051027  | 104202    | 195   lb      |Weight  
    1424285941000610    | 20051027  | 104202    | 104   mm Hg   |BP Systolic  
    1424285941000610    | 20051027  | 104202    | 70    mm Hg   |BP Diastolic  
    1424285941000610    | 20060629  | 092852    | 61.5  in      |Height  
    1424285941000610    | 20060629  | 092852    | 209   lb      |Weight  
    

    我设法打破了我想要使用多个案例陈述但我得到的东西看起来像这样:

    PID Obs_Date    |Obs_Time   |smoking status |bp_dia |bp_sys |Height |Weight  
    1424285963050610    |20121203   |161415     |NULL   |NULL   |NULL   |180lb  
    1424285963050610    |20121203   |161415     |NULL   |NULL   |70in   |NULL    
    1424285963050610    |20121203   |161415     |NULL   |138mm Hg   |NULL   |NULL  
    1424285963050610    |20121203   |161415     |80mm Hg    |NULL   |NULL   |NULL 
    

    哪个技术上可以满足我的需求,但我知道它不正确所以我希望我可以根据观察日期将它看作下面的行组合

    理想情况下,它看起来像这样:

    PID |Obs_Date |Obs_Time |smoking status |bp_dia |bp_sys |Height |Weight
    
    1424285963050610    |20121203   |161415     |N  |80 mmHg  |110 mmHg  |null |null
    

    我也尝试过使用嵌套替换,但我最终遇到了同样的问题,因为它只在一个列中。

    我正在使用SQL server 2008。任何帮助是极大的赞赏。

1 个答案:

答案 0 :(得分:0)

有几种方法可以做到这一点。 一种是通过相关子查询选择数据。 另一种是通过表值子查询。 另一种方法是只按三个关键字段进行分组,然后执行min并处理空值。 我将在下面显示表值选项。 您可以看到我已将主要患者数据与每个观察结果分开,因为它是自己的数据集。然后将它们链接到3个关键字段。

SELECT 
   pd.PID, pd.Observation_Date, pd.Observation_Time,
   ss.Obs_Value,
   bpd.Obs_Value,
   bps.Obs_value,
   h.Obs_Value,
   w.Obs_Value
FROM (SELECT DISTINCT PID, Observation_Date, Observation_Time FROM patient_data) AS pd
     LEFT OUTER JOIN (SELECT PID, Observation_Date, Observation_Time, Obs_Value FROM patient_data WHERE Observation = 'Smoking Status') AS ss ON (pd.PID = ss.PID AND pd.Observation_Date = ss.Observation_Date AND pd.Observation_Time = ss.Observation_Time)
     LEFT OUTER JOIN (SELECT PID, Observation_Date, Observation_Time, Obs_Value FROM patient_data WHERE Observation = 'BP Diastolic') AS bpd ON (pd.PID = bpd.PID AND pd.Observation_Date = bpd.Observation_Date AND pd.Observation_Time = bpd.Observation_Time)
     LEFT OUTER JOIN (SELECT PID, Observation_Date, Observation_Time, Obs_Value FROM patient_data WHERE Observation = 'BP Systolic') AS bps ON (pd.PID = bps.PID AND pd.Observation_Date = bps.Observation_Date AND pd.Observation_Time = bps.Observation_Time)
     LEFT OUTER JOIN (SELECT PID, Observation_Date, Observation_Time, Obs_Value FROM patient_data WHERE Observation = 'Height') AS h ON (pd.PID = h.PID AND pd.Observation_Date = h.Observation_Date AND pd.Observation_Time = h.Observation_Time)
     LEFT OUTER JOIN (SELECT PID, Observation_Date, Observation_Time, Obs_Value FROM patient_data WHERE Observation = 'Weight') AS w ON (pd.PID = w.PID AND pd.Observation_Date = w.Observation_Date AND pd.Observation_Time = w.Observation_Time)

这是一个可能是首选解决方案的例子,它只是分组并取最大值

SELECT
   pd.PID, pd.Observation_Date, pd.Observation_Time,
   MAX(CASE WHEN pd.Observation = 'Smoking Status' THEN pd.Obs_Value ELSE '' END) AS [smoking status],
   MAX(CASE WHEN pd.Observation = 'BP Diastolic' THEN pd.Obs_Value ELSE '' END) AS [bp_dia],
   MAX(CASE WHEN pd.Observation = 'BP Systolic' THEN pd.Obs_Value ELSE '' END) AS [bp_sys],
   MAX(CASE WHEN pd.Observation = 'Height' THEN pd.Obs_Value ELSE '' END) AS [Height],
   MAX(CASE WHEN pd.Observation = 'Weight' THEN pd.Obs_Value ELSE '' END) AS [Weight]
FROM patient_data
GROUP BY pd.PID, pd.Observation_Date, pd.Observation_Time

所有这些都是空气密码,未经测试。