Sql 如何将垂直表格转换为水平表格?

Sql 如何将垂直表格转换为水平表格?,sql,sql-server,linq-to-sql,parent-child,Sql,Sql Server,Linq To Sql,Parent Child,我有一个餐桌上的人: Id Name 1 Person1 2 Person2 3 Person3 我有它的子表配置文件: Id PersonId FieldName Value 1 1 Firstname Alex 2 1 Lastname Balmer 3 1 Email some_email@test.com 4 1 Phone +1 2 30004000 我想在一行中从这两个表中获取数据,

我有一个餐桌上的人:

Id Name
1  Person1
2  Person2
3  Person3
我有它的子表配置文件:

Id PersonId FieldName  Value
1  1        Firstname  Alex
2  1        Lastname   Balmer
3  1        Email      some_email@test.com
4  1        Phone      +1 2 30004000
我想在一行中从这两个表中获取数据,如下所示:

Id Name     Firstname Lastname  Email                Phone 
1  Person1  Alex      Balmer    some_email@test.com  +1 2 30004000
  • 在这样的一行中获得这些垂直(键、值)值的最佳查询是什么?现在我有一个问题,我完成了子表到父表的四个连接,因为我需要得到这四个字段。一些优化当然是可能的
  • 我希望在添加新字段(键、值)时能够轻松地修改此查询。最好的方法是什么?创建一些存储过程
  • 我希望在我的DB层(C#)中有强类型,并使用LINQ(编程时),因此这意味着当我在概要表中添加一些新的键、值对时,如果可能的话,我希望在DB和C#中进行最小的修改。事实上,我正在尝试在这种情况下获得一些最佳实践

    Select 
        P.ID
        , P.Name
        , Case When C.FieldName = 'FirstName' Then C.Value Else NULL END AS FirstName
        , Case When C.FieldName = 'LastName' Then C.Value Else NULL END AS LastName
        , Case When C.FieldName = 'Email' Then C.Value Else NULL END AS Email
        , Case When C.FieldName = 'Phone' Then C.Value Else NULL END AS Phone  
    From Person AS P
    Inner JOIN Child AS C
    ON P.ID = C.PersonID
    

    你可以用枢轴;不确定哪一个最容易添加新列。

    强类型字段的最佳优化方法是:

    CREATE TABLE Persons
    (PersonID     int identity(1,1) primary key
    ,Firstname    varchar(...)
    ,Lastname     varchar(...)
    ,Email        varchar(...)
    ,Phone        varchar(...)
    ,....
    )
    
    那么最优化的查询将是:

    SELECT
        PersonID,Firstname,Lastname,Email,Phone
        FROM Persons
        WHERE ...
    
    将所有主列添加到persons表中。如果需要专门化,请创建其他表:

    --one person can play many instruments with this table
    CREATE TABLE PersonMusicians
    (PersonID               int           --pk   fk to Persons.PersonID     
    ,InstrumentCode         char(1)       --pk
    ,...
    )
    
    --only one row per person with this table
    CREATE TABLE PersonTeachers
    (PersonID               int            --pk   fk to Persons.PersonID    
    ,FavoriteSubjectCode    char(1)
    ,SchoolName             varchar(...)
    )
    
    如果您必须拥有无限的动态属性字段,那么我将尽可能完整地创建上述结构(尽可能多的公共字段),然后创建一个“AdditionalInfo”表,在其中存储所有信息,如:

    AdditionalInfoFields
    FieldID    int identity(1,1) primary key
    FieldName  varchar(...)
    
    AdditionalInfo
    AdditionalInfoID   int identity(1,1) primary key
    PersonID           int   fk to Persons.PersonID  
    FieldID            int   fk to AdditionalInfoFields.FieldID    
    FieldValue         varchar(..) or you can look into sql_variant
    
    AdditionalInfo.PersonID+FieldID
    上有一个索引,如果您要搜索所有具有属性X的人,那么还有另一个类似
    AdditionalInfo.FieldID+PersonID

    除上述任何一项外,您将需要使用您在选项#1中提到的四个左侧外部联接:


    您始终可以使用此4个左联接查询的索引创建一个物化视图,并为您预先计算数据,这将加快查询速度。

    如果您在设计时知道查询应发出哪些列,为什么在概要文件表中需要一个开放式字段结构?
    SELECT
        P.ID, p.Name
            , p1.Value AS Firstname
            , p2.value AS Lastname     
            , p3.Value AS Email
            , p4.Value AS Phone
        FROM Persons                 p
            LEFT OUTER JOIN Profile p1 ON p.PersonID=p1.PersonID AND p1.FieldName='Firstname'
            LEFT OUTER JOIN Profile p1 ON p.PersonID=p1.PersonID AND p1.FieldName='Lastname'
            LEFT OUTER JOIN Profile p1 ON p.PersonID=p1.PersonID AND p1.FieldName='Email'
            LEFT OUTER JOIN Profile p1 ON p.PersonID=p1.PersonID AND p1.FieldName='Phone'
        WHERE ....