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

非常感谢您的帮助

这是一个非常糟糕的设计...我希望您需要这个来解决这个问题...

一般规则:
每当你想创建名称有索引的列时(如 Date1Date2),这就是你需要相关端 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])