【问题标题】:SQL return values as fields based on key and value type table - PIVOT, CASE, etc?SQL 将值作为基于键和值类型表的字段返回 - PIVOT、CASE 等?
【发布时间】:2011-08-04 14:06:23
【问题描述】:

使用 SQL Server 2005 我有以下表格:

价值:

ValueID  UserID    ValueTypeID  ValueKey  Text  Number
------------------------------------------------------
1        345       1            NAME      Bob   NULL
2        345       2            AGE       NULL  30
3        689       1            NAME      Sam   NULL
4        689       2            AGE       NULL  45

值类型:

ValueTypeID  CodeName
---------------------
1            TEXT
2            NUMBER

我希望得到如下结果:

UserID  Name  Age
-----------------
345     Bob   30
689     Sam   45

我确信这是可能的,使用枢轴和一些案例陈述?有更多的 ValueKey,甚至更多的 ValueType,但这会让我继续前进。我事先知道 ValueKeys 的列表,所以这应该意味着我可以避免动态查询。

【问题讨论】:

    标签: sql sql-server-2005 pivot


    【解决方案1】:

    经典的数据透视查询。然后,您可以根据需要使用 ValueTypeID:

    SELECT UserID, 
           MAX(
               CASE WHEN ValueKey = 'NAME' 
                    THEN 
                        CASE WHEN ValueTypeID = 1 
                                 THEN Text 
                             WHEN ValueTypeID = 2
                                 THEN Number 
                             WHEN ValueTypeID = 3
                                 THEN Date
                             ELSE NULL
                        END
                    ELSE NULL 
               END
           ) AS Name,
           MAX(
               CASE WHEN ValueKey = 'AGE' 
                    THEN 
                        CASE WHEN ValueTypeID = 1 
                                 THEN Text 
                             WHEN ValueTypeID = 2
                                 THEN Number 
                             WHEN ValueTypeID = 3
                                 THEN Date
                             ELSE NULL
                        END
                    ELSE NULL 
               END
           ) AS Age,
           MAX(
               CASE WHEN ValueKey = 'DATEBIRTH' 
                    THEN 
                        CASE WHEN ValueTypeID = 1 
                                 THEN Text 
                             WHEN ValueTypeID = 2
                                 THEN Number 
                             WHEN ValueTypeID = 3
                                 THEN Date
                             ELSE NULL
                        END
                    ELSE NULL 
               END
           ) AS DateBirth
    FROM Value
    GROUP BY UserID
    

    但它可能没用,你可以用更少的代码来减少通用性:

    SELECT UserID, 
           MAX(
               CASE WHEN ValueKey = 'NAME' 
                    THEN Text -- I know that name is a string
                    ELSE NULL 
               END
           ) AS Name,
           MAX(
               CASE WHEN ValueKey = 'AGE' 
                    THEN Number -- I know that age is a number
                    ELSE NULL 
               END
           ) AS Age,
           MAX(
               CASE WHEN ValueKey = 'DATEBIRTH' 
                    THEN Date -- I know that date of birth is a date
                    ELSE NULL 
               END
           ) AS DateBirth
    FROM Value
    GROUP BY UserID
    

    【讨论】:

    • 如何扩展它来处理出生日期键和另一个 DATE 值类型?
    • +1,你也可以省略ELSE NULL,因为如果没有指定ELSE,它是隐含的。
    【解决方案2】:

    解决方案应该是重新设计表格。 valueType 查找在实现时完全没用。您应该只有一个“ValueText”列而不是“Text”、“Number”……并将所有值存储在该 1 列中。那么这将是一个简单的join 语句。

    【讨论】:

    • 不幸的是,我正在查询旧数据库。我目前无法更改其设计。此外,Text 是一个 nvarchar 字段,数字是一个 int 字段,还有一个 datetime 类型的日期字段等。
    【解决方案3】:

    您可以按 UserID 分组并使用子查询来获取字段值。

    declare @T table
    (
      ValueID int,
      UserID int,
      ValueTypeID int,
      ValueKey varchar(10),
      Text varchar(10),
      Number int
    )
    
    insert into @T values
    (1,        345,       1,            'NAME',      'Bob',   NULL),
    (2,        345,       2,            'AGE',       NULL,    30),
    (3,        689,       1,            'NAME',      'Sam',   NULL),
    (4,        689,       2,            'AGE',       NULL,    45)
    
    select T1.UserID,
           (select [Text]
            from @T as T2
            where T1.UserID = T2.UserID and
                  T2.ValueKey = 'NAME') as Name,
           (select Number
            from @T as T2
            where T1.UserID = T2.UserID and
                  T2.ValueKey = 'AGE') as Age
    from @T as T1
    group by T1.UserID
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-18
      相关资源
      最近更新 更多