【问题标题】:horizontal to vertical table transformation in SQL Server 2005SQL Server 2005 中的水平到垂直表转换
【发布时间】:2010-03-08 17:11:08
【问题描述】:

我有一个页面,可以从表格中动态构建表单输入字段,允许用户在表单中输入输入。每个输入都是 _info 表中的一个字段。

我想要在一行中显示用户的所有条目的报告。每个字段条目是一行。所以我需要获取垂直数据并使其水平。有许多具有不同配置的不同形式,因此必须是动态的。我遇到过很多关于跨表数据透视的文章,但它们只适用于聚合/总和。

Registration_Info 表对于一个表单提交有多个条目。我需要列出这些水平,每个 form_field.label 作为报告的字段名。

以下是表格布局示例:

FORM
——————————————
FORM_ID|FORM_NAME
500|“Custom Form 1″

FORM_FIELD
——————————————
FORM_FIELD_ID|FORM_ID|LABEL
1|500|“Field 1″
2|500|“Field 2″

REGISTRATION
——————————————
REG_ID|FORM_ID|USER_ID
23|500|45
24|500|98

REGISTRATION_INFO
——————————————
REG_ID|FORM_FIELD_ID|FIELD_VALUE
23|1|“My Name”
24|2|“My City”

Required Report Output:
REG_ID |Field 1 |Field 2 |FORM_ID |USER_ID
———————————————————————————————
23 |My Name |My City |500 |45
24 |Another Name |Another City |500 |98 

【问题讨论】:

    标签: sql sql-server pivot crosstab


    【解决方案1】:

    我相信这会解决您的需求:

    静态枢轴

    create table #form
    (
        form_id int,
        form_name varchar(50)
    )
    create table #form_field
    (
        form_field_id int,
        form_id int,
        label varchar(50)
    )
    create table #registration
    (
        reg_id int,
        form_id int,
        userid int
    )
    create table #registration_info
    (
        reg_id int,
        form_field_id int,
        field_value varchar(50)
    )
    
    insert into #form values(500, 'Custom Form 1')
    insert into #form_field values(1, 500, 'Field 1')
    insert into #form_field values(2, 500, 'Field 2')
    insert into #registration values(23, 500, 45)
    insert into #registration values(24, 500, 98)
    insert into #registration_info values(23, 1, 'My Name')
    insert into #registration_info values(24, 2, 'My City')
    
    
    select r.reg_id
        , IsNull(p.[Field 1], '') as Field1
        , IsNull(p.[Field 2], '') as Field2
        , r.form_id
        , r.userid
    from 
    (
        select ri.reg_id
            , ri.field_value
            , ff.form_id
            , ff.label
        from #registration_info ri
        inner join #form_field ff
            on ri.form_field_id = ff.form_field_id
    ) riff
    pivot 
    (
        max(field_value)
        for label in ([Field 1], [Field 2])
    ) p
    JOIN #registration r
        on p.form_id = r.form_id
        AND p.reg_id = r.reg_id
    

    这是一个带有工作版本的sqlfiddle

    动态枢轴 此版本将首先获取字段列表,然后对其进行旋转。

    create table form
    (
        form_id int,
        form_name varchar(50)
    )
    create table form_field
    (
        form_field_id int,
        form_id int,
        label varchar(50)
    )
    create table registration
    (
        reg_id int,
        form_id int,
        userid int
    )
    create table registration_info
    (
        reg_id int,
        form_field_id int,
        field_value varchar(50)
    )
    
    insert into form values(500, 'Custom Form 1')
    insert into form_field values(1, 500, 'Field 1')
    insert into form_field values(2, 500, 'Field 2')
    insert into registration values(23, 500, 45)
    insert into registration values(24, 500, 98)
    insert into registration_info values(23, 1, 'My Name')
    insert into registration_info values(24, 2, 'My City')
    
    DECLARE @cols AS VARCHAR(MAX),
        @query  AS VARCHAR(MAX);
    
    SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.label) 
                FROM dbo.form_field c
                FOR XML PATH(''), TYPE
                ).value('.', 'VARCHAR(MAX)') 
            ,1,1,'')
    
    set @query = 'SELECT r.reg_id, ' + @cols + ', r.form_id, r.userid from 
                (
                    select ri.reg_id
                        , ri.field_value
                        , ff.form_id
                        , ff.label
                    from registration_info ri
                    inner join form_field ff
                        on ri.form_field_id = ff.form_field_id
               ) riff
                pivot 
                (
                     max(field_value)
                    for label in (' + @cols + ')
                ) p 
                JOIN registration r
                    on p.form_id = r.form_id
                    AND p.reg_id = r.reg_id'
    
    
    execute(@query)
    

    【讨论】:

    • 可能需要使最终结果动态 sql,因为枢轴列的数量将是未知的。循环遍历指定表单的字段,然后添加数据透视列。 Pivot 是通用解决方案的必经之路。
    • @ulty4life 你可能是对的,我更新了我的答案以包含一个动态 SQL PIVOT。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-09
    • 2020-02-25
    • 1970-01-01
    • 2018-12-31
    • 2017-08-07
    • 1970-01-01
    • 2013-12-22
    相关资源
    最近更新 更多