代码之家  ›  专栏  ›  技术社区  ›  JohnIdol

SQL2005中动态透视所需的帮助

  •  1
  • JohnIdol  · 技术社区  · 15 年前

    我有一个名称-值对表,在其中存储标记:

    TAGID | NAME | VALUE
    

    我有一张表,上面写着这些标签适用于

    THINGID | TAGID
    

    如果列/字段都是给定thingid的可能标记名(标记表中的名称字段),并且值是相应的标记值,则需要查询来生成结果集。

    THINGID | TAGNAME1 | TAGNAME2 | ... |etc.
    

    我可以找到固定列的例子,但没有这样的例子。

    1 回复  |  直到 15 年前
        1
  •  1
  •   Stanislav Kniazev    15 年前

    与稍有不同的模式(thing_id,tag_name,tag_value)相似的东西-不带tags表:

    CREATE PROCEDURE dbo.PivotData(@table VARCHAR(128), @basefield
    VARCHAR(128), @namefield VARCHAR(128), @valuefield VARCHAR(128))
    AS
    DECLARE
     @sql NVARCHAR(MAX)
    SET @sql =
     'DECLARE
     @colName VARCHAR(128),
     @sqlBegin NVARCHAR(MAX),
     @sqlMiddle NVARCHAR(MAX),
     @sqlEnd NVARCHAR(MAX),
     @counter INT
     SET @counter = 1
     SET @sqlBegin = N''SELECT DISTINCT t0.'' + ''' + QUOTENAME(@basefield) + '''
     SET @sqlMiddle = N'' FROM '' + ''' + QUOTENAME(@table) + ''' + '' AS t0 ''
     DECLARE cols CURSOR FOR
     SELECT DISTINCT TOP 100 PERCENT ' + QUOTENAME(@namefield) + '
     FROM ' + QUOTENAME(@table) + '
     WHERE ' + QUOTENAME(@basefield) + ' IS NOT NULL
     ORDER BY ' + QUOTENAME(@namefield) + '
     OPEN cols
     FETCH NEXT FROM cols INTO @colName
     WHILE @@FETCH_STATUS = 0 BEGIN
     SET @sqlBegin = @sqlBegin + '', t'' + CAST(@counter AS VARCHAR) +
    ''.'' + ''' + QUOTENAME(@valuefield) + ''' + '' AS '' +
    QUOTENAME(@colName) + ''''
     SET @sqlMiddle = @sqlMiddle + '' LEFT OUTER JOIN '' + ''' +
      QUOTENAME(@table) + ''' + '' AS t'' + CAST(@counter AS VARCHAR) +
    '' ON t0.'' + ''' +
      QUOTENAME(@basefield) + ''' + '' = t'' + CAST(@counter AS VARCHAR)
    + ''.'' + ''' +
      QUOTENAME(@basefield) + ''' + '' AND t'' + CAST(@counter AS
    VARCHAR) + ''.'' + ''' + QUOTENAME(@namefield) + ''' + ''='' +
    QUOTENAME(@colName, '''''''') + ''''
     SET @counter = @counter + 1
     FETCH NEXT FROM cols INTO @colName
     END
     CLOSE cols
     DEALLOCATE cols
     SET @sqlEnd = '' WHERE t0.'' + ''' + QUOTENAME(@basefield) + ''' + ''
    IS NOT NULL''
     DECLARE @sql NVARCHAR(MAX)
     SET @sql = @sqlBegin + @sqlMiddle + @sqlEnd
     EXEC sp_executesql @sql'
    EXEC sp_executesql @sql
    RETURN 0
    GO
    CREATE TABLE test_data (
    id int identity primary key,
    person_id int,
    person_data_field VARCHAR (128),
    person_data_value VARCHAR (128)
    )
    GO
    INSERT INTO dbo.test_data (person_id, person_data_field, person_data_value)
    VALUES (1, 'Name', 'John')
    INSERT INTO dbo.test_data (person_id, person_data_field, person_data_value)
    VALUES (1, 'Surname', 'Smith')
    INSERT INTO dbo.test_data (person_id, person_data_field, person_data_value)
    VALUES (1, 'Email', 'John@Smith.com')
    INSERT INTO dbo.test_data (person_id, person_data_field, person_data_value)
    VALUES (2, 'Name', 'Sarah')
    INSERT INTO dbo.test_data (person_id, person_data_field, person_data_value)
    VALUES (2, 'Surname', 'Lee')
    INSERT INTO dbo.test_data (person_id, person_data_field, person_data_value)
    VALUES (2, 'Phone', '012345678')
    GO
    EXEC [dbo].[PivotData] @table='test_data',
    @basefield='person_id', @namefield='person_data_field', @valuefield='person_data_value'
    GO
    

    我发现这样做的速度太慢了,不再进一步调整它,但它可以满足您的要求。