Pivot/Unpivot 和排名配对数据
Pivot/Unpivot and Ranking paired data
在每行有 9 个匹配对的 table 中,是否可以使用 Pivot 生成列,例如以下内容:
SELECT TOP 1
ID,
HOME_APPDTE1,
HOMENUMBER1,
HOME_APPDTE2,
HOMENUMBER2,
HOME_APPDTE3,
HOMENUMBER3,
WORK_APPDTE1,
WORKNUMBER2,
WORK_APPDTE2,
WORKNUMBER3,
WORK_APPDTE3,
WORKNUMBER1,
MOBILE_APPDTE1,
MOBILENUMBER1,
MOBILE_APPDTE2,
MOBILENUMBER2,
MOBILE_APPDTE3,
MOBILENUMBER3
FROM
Telephone_Numbers
returns
ID HOME_APPDTE1 HOMENUMBER1 HOME_APPDTE2 HOMENUMBER2 HOME_APPDTE3 HOMENUMBER3 WORK_APPDTE1 WORKNUMBER2 WORK_APPDTE2 WORKNUMBER3 WORK_APPDTE3 WORKNUMBER1 MOBILE_APPDTE1 MOBILENUMBER1 MOBILE_APPDTE2 MOBILENUMBER2 MOBILE_APPDTE3 MOBILENUMBER3
23 2016-11-25 111111111 2015-06-22 222222222 2015-02-22 333333333 2017-01-25 444444444 2016-02-12 555555555 2015-06-13 666666666 2017-05-18 777777777 2016-12-23 888888888 2016-01-11 999999999
但我在
ID Type Date_Changed Tel_Number Rank
23 Home 2016-11-25 111111111 1
23 Home 2015-06-22 222222222 2
23 Home 2015-02-22 333333333 3
23 Work 2017-01-25 444444444 1
23 Work 2016-02-12 555555555 2
23 Work 2015-06-13 666666666 3
23 Mobile 2017-05-18 777777777 1
23 Mobile 2016-12-23 888888888 2
23 Mobile 2016-01-11 999999999 3
非常感谢您的帮助
这是一个非常糟糕的设计...我希望您需要这个来解决这个问题...
一般规则:
每当你想创建名称有索引的列时(如 Date1
、Date2
),这就是你需要相关端 table!
的明确标志
您可以尝试这样的操作:
DECLARE @mockup TABLE(ID INT,HOME_APPDTE1 DATE,HOMENUMBER1 VARCHAR(100)
,HOME_APPDTE2 DATE,HOMENUMBER2 VARCHAR(100)
,HOME_APPDTE3 DATE,HOMENUMBER3 VARCHAR(100)
,WORK_APPDTE1 DATE,WORKNUMBER1 VARCHAR(100)
,WORK_APPDTE2 DATE,WORKNUMBER2 VARCHAR(100));
SET DATEFORMAT ymd;
INSERT INTO @mockup VALUES
(23,'2014-11-25','111111111'
,'2011-05-03','222222222'
,'2015-12-12','333333333'
,'2014-04-02','444444444'
,'2014-02-24','555555555');
WITH Normalized AS
(
SELECT ID,'Home' AS [Type],HOME_APPDTE1 AS DateChanged,HOMENUMBER1 AS Tel_Number,1 AS [Rank] FROM @mockup
UNION ALL SELECT ID,'Home',HOME_APPDTE2,HOMENUMBER2,2 FROM @mockup
UNION ALL SELECT ID,'Home',HOME_APPDTE3,HOMENUMBER3,3 FROM @mockup
UNION ALL SELECT ID,'Work',WORK_APPDTE1,WORKNUMBER1,1 FROM @mockup
UNION ALL SELECT ID,'Work',WORK_APPDTE2,WORKNUMBER2,2 FROM @mockup
)
SELECT *
FROM Normalized
ORDER BY ID,[Type],[Rank];
你应该做什么:
您tableTelephone_Numbers
中的ID是假定的人的ID。所以可能有一个人 table。现在你需要这样的东西:
- 一个
phone_type
目录
- a
phone_number
table,你需要的地方
PhoneID (PK), OwnerID (FK), PhoneTypeID (FK), ChangeDate and Number
。您可能需要一个 Rank
列,如果排名不是从更改日期的顺序中获取的...
事实上,您要实现的目标结构大致就是您应该如何实际存储数据的结构...
假设您不需要动态,另一种选择是使用 CROSS APPLY.
此外,假设您不需要动态解决方案。
例子
Select A.ID
,B.*
From YourTable A
Cross Apply ( values ('Home' ,HOME_APPDTE1 ,HOMENUMBER1 ,1)
,('Home' ,HOME_APPDTE2 ,HOMENUMBER2 ,2)
,('Home' ,HOME_APPDTE3 ,HOMENUMBER3 ,3)
,('Work' ,WORK_APPDTE1 ,WORKNUMBER1 ,1)
,('Work' ,WORK_APPDTE2 ,WORKNUMBER2 ,2)
,('Work' ,WORK_APPDTE3 ,WORKNUMBER2 ,3)
,('Mobile',MOBILE_APPDTE1,MOBILENUMBER1,1)
,('Mobile',MOBILE_APPDTE2,MOBILENUMBER2,2)
,('Mobile',MOBILE_APPDTE3,MOBILENUMBER3,3)
) B ([Type],[DateChanged],[Tel_Number],[Rank])
在每行有 9 个匹配对的 table 中,是否可以使用 Pivot 生成列,例如以下内容:
SELECT TOP 1 ID, HOME_APPDTE1, HOMENUMBER1, HOME_APPDTE2, HOMENUMBER2, HOME_APPDTE3, HOMENUMBER3, WORK_APPDTE1, WORKNUMBER2, WORK_APPDTE2, WORKNUMBER3, WORK_APPDTE3, WORKNUMBER1, MOBILE_APPDTE1, MOBILENUMBER1, MOBILE_APPDTE2, MOBILENUMBER2, MOBILE_APPDTE3, MOBILENUMBER3 FROM Telephone_Numbers
returns
ID HOME_APPDTE1 HOMENUMBER1 HOME_APPDTE2 HOMENUMBER2 HOME_APPDTE3 HOMENUMBER3 WORK_APPDTE1 WORKNUMBER2 WORK_APPDTE2 WORKNUMBER3 WORK_APPDTE3 WORKNUMBER1 MOBILE_APPDTE1 MOBILENUMBER1 MOBILE_APPDTE2 MOBILENUMBER2 MOBILE_APPDTE3 MOBILENUMBER3 23 2016-11-25 111111111 2015-06-22 222222222 2015-02-22 333333333 2017-01-25 444444444 2016-02-12 555555555 2015-06-13 666666666 2017-05-18 777777777 2016-12-23 888888888 2016-01-11 999999999
但我在
ID Type Date_Changed Tel_Number Rank 23 Home 2016-11-25 111111111 1 23 Home 2015-06-22 222222222 2 23 Home 2015-02-22 333333333 3 23 Work 2017-01-25 444444444 1 23 Work 2016-02-12 555555555 2 23 Work 2015-06-13 666666666 3 23 Mobile 2017-05-18 777777777 1 23 Mobile 2016-12-23 888888888 2 23 Mobile 2016-01-11 999999999 3
非常感谢您的帮助
这是一个非常糟糕的设计...我希望您需要这个来解决这个问题...
一般规则:
每当你想创建名称有索引的列时(如 Date1
、Date2
),这就是你需要相关端 table!
您可以尝试这样的操作:
DECLARE @mockup TABLE(ID INT,HOME_APPDTE1 DATE,HOMENUMBER1 VARCHAR(100)
,HOME_APPDTE2 DATE,HOMENUMBER2 VARCHAR(100)
,HOME_APPDTE3 DATE,HOMENUMBER3 VARCHAR(100)
,WORK_APPDTE1 DATE,WORKNUMBER1 VARCHAR(100)
,WORK_APPDTE2 DATE,WORKNUMBER2 VARCHAR(100));
SET DATEFORMAT ymd;
INSERT INTO @mockup VALUES
(23,'2014-11-25','111111111'
,'2011-05-03','222222222'
,'2015-12-12','333333333'
,'2014-04-02','444444444'
,'2014-02-24','555555555');
WITH Normalized AS
(
SELECT ID,'Home' AS [Type],HOME_APPDTE1 AS DateChanged,HOMENUMBER1 AS Tel_Number,1 AS [Rank] FROM @mockup
UNION ALL SELECT ID,'Home',HOME_APPDTE2,HOMENUMBER2,2 FROM @mockup
UNION ALL SELECT ID,'Home',HOME_APPDTE3,HOMENUMBER3,3 FROM @mockup
UNION ALL SELECT ID,'Work',WORK_APPDTE1,WORKNUMBER1,1 FROM @mockup
UNION ALL SELECT ID,'Work',WORK_APPDTE2,WORKNUMBER2,2 FROM @mockup
)
SELECT *
FROM Normalized
ORDER BY ID,[Type],[Rank];
你应该做什么:
您tableTelephone_Numbers
中的ID是假定的人的ID。所以可能有一个人 table。现在你需要这样的东西:
- 一个
phone_type
目录 - a
phone_number
table,你需要的地方PhoneID (PK), OwnerID (FK), PhoneTypeID (FK), ChangeDate and Number
。您可能需要一个Rank
列,如果排名不是从更改日期的顺序中获取的...
事实上,您要实现的目标结构大致就是您应该如何实际存储数据的结构...
假设您不需要动态,另一种选择是使用 CROSS APPLY.
此外,假设您不需要动态解决方案。
例子
Select A.ID
,B.*
From YourTable A
Cross Apply ( values ('Home' ,HOME_APPDTE1 ,HOMENUMBER1 ,1)
,('Home' ,HOME_APPDTE2 ,HOMENUMBER2 ,2)
,('Home' ,HOME_APPDTE3 ,HOMENUMBER3 ,3)
,('Work' ,WORK_APPDTE1 ,WORKNUMBER1 ,1)
,('Work' ,WORK_APPDTE2 ,WORKNUMBER2 ,2)
,('Work' ,WORK_APPDTE3 ,WORKNUMBER2 ,3)
,('Mobile',MOBILE_APPDTE1,MOBILENUMBER1,1)
,('Mobile',MOBILE_APPDTE2,MOBILENUMBER2,2)
,('Mobile',MOBILE_APPDTE3,MOBILENUMBER3,3)
) B ([Type],[DateChanged],[Tel_Number],[Rank])