在 SQL Server 2008 中使用 Unpivot 或 Cross Apply 规范化数据
Posted
技术标签:
【中文标题】在 SQL Server 2008 中使用 Unpivot 或 Cross Apply 规范化数据【英文标题】:Normalizing data using Unpivot or Cross Apply in SQL Server 2008 【发布时间】:2014-09-03 20:40:09 【问题描述】:我无法还原某些数据。我在这里看到了其他用于取消透视表的示例,但我有需要取消透视表的对。我的数据集中实际上有 10 多个疾病/日期对,但我选择了三对来简化示例。
这是我的源数据:
MRN GUMCID Event BreastID BreastDate ColonID ColonDate PancID PancDate
2000012 90000001 event_1 42 1/1/2000 43 8/5/2014 44 8/6/2012
2008006 90000020 event_1 102 5/7/2003 103 9/11/2012
2000012 90002002 event_1 900 8/5/2004 902 12/5/2009
2000012 90002002 event_2 1000 9/6/2006
这是我需要将其转换为的内容:
MRN GUMCID Event TissueType Date ID
2000012 90000001 event_1 BreastID 1/1/2000 42
2000012 90000001 event_1 ColonID 8/5/2014 43
2000012 90000001 event_1 PancID 8/6/2012 44
2008006 90000020 event_1 BreastID 5/7/2003 102
2008006 90000020 event_1 ColonID 9/11/2012 103
2000012 90002002 event_1 BreastID 8/5/2004 900
2000012 90002002 event_1 PancID 12/5/2009 902
2000012 90002002 event_2 BreastID 9/6/2006 1000
我摸索过 unpivot 和 cross apply ,但似乎无法完成这项工作。任何想法表示赞赏!
【问题讨论】:
pancid 的日期从何而来? 它在源数据示例中,您必须向右滚动才能看到它。它位于 PancDate 列中。 啊抱歉手机浏览器不显示滚动条 【参考方案1】:测试数据
DECLARE @TABLE TABLE
(MRN INT, GUMCID INT, [Event] VARCHAR(10), BreastID INT,
BreastDate DATE, ColonID INT, ColonDate DATE, PancID INT, PancDate DATE)
INSERT INTO @TABLE VALUES
(2000012, 90000001,'event_1', 42 ,'1/1/2000', 43 ,'8/5/2014' , 44 ,'8/6/2012'),
(2008006, 90000020,'event_1', 102 ,'5/7/2003', 103 ,'9/11/2012', NULL, NULL),
(2000012, 90002002,'event_1', 900 ,'8/5/2004', 902 ,'12/5/2009', NULL, NULL),
(2000012, 90002002,'event_2', 1000 ,'9/6/2006', NULL, NULL , NULL, NULL)
查询
SELECT MRN
,GUMCID
,[Event]
,TissueType
,CONVERT(VARCHAR(10),
CASE
WHEN TissueType = 'BreastID' THEN BreastDate
WHEN TissueType = 'ColonID' THEN ColonDate
WHEN TissueType = 'PancID' THEN PancDate
END, 103) AS [Date]
,ID
FROM @Table t
UNPIVOT (ID FOR TissueType IN (BreastID, ColonID, PancID)
)up
结果
╔═════════╦══════════╦═════════╦════════════╦════════════╦══════╗
║ MRN ║ GUMCID ║ Event ║ TissueType ║ Date ║ ID ║
╠═════════╬══════════╬═════════╬════════════╬════════════╬══════╣
║ 2000012 ║ 90000001 ║ event_1 ║ BreastID ║ 01/01/2000 ║ 42 ║
║ 2000012 ║ 90000001 ║ event_1 ║ ColonID ║ 05/08/2014 ║ 43 ║
║ 2000012 ║ 90000001 ║ event_1 ║ PancID ║ 06/08/2012 ║ 44 ║
║ 2008006 ║ 90000020 ║ event_1 ║ BreastID ║ 07/05/2003 ║ 102 ║
║ 2008006 ║ 90000020 ║ event_1 ║ ColonID ║ 11/09/2012 ║ 103 ║
║ 2000012 ║ 90002002 ║ event_1 ║ BreastID ║ 05/08/2004 ║ 900 ║
║ 2000012 ║ 90002002 ║ event_1 ║ ColonID ║ 05/12/2009 ║ 902 ║
║ 2000012 ║ 90002002 ║ event_2 ║ BreastID ║ 06/09/2006 ║ 1000 ║
╚═════════╩══════════╩═════════╩════════════╩════════════╩══════╝
【讨论】:
谢谢!有没有一种简单的方法来提取 BreastID/ColonID/PancID 列名称以用作此处的 TissueType 值,而不是对它们进行硬编码?【参考方案2】:select mrd, gumcid, event, tissuetype, date, id
from tbl
cross apply (
values
('breastid', breastid, breastdate),
('colonid', colonid, colondate),
('pancid', pancid, pancdate)
) t(tissuetype, id, date)
where id is not null
【讨论】:
谢谢!有没有一种简单的方法来提取 BreastID/ColonID/PancID 列名称以用作此处的 TissueType 值,而不是对它们进行硬编码?以上是关于在 SQL Server 2008 中使用 Unpivot 或 Cross Apply 规范化数据的主要内容,如果未能解决你的问题,请参考以下文章
Query (SQL Server 2008 Express) 在 SQL Server Management Studio 中有效,但在 Delphi 中使用 ADODB 无效
在 sql server 2008 中使用 unicode 文本
安装SQL SERVER 2008,出现“查找sql server 2008安装媒体”的问题