从表中插入列别名以查询结果

时间:2017-09-27 08:18:35

标签: sql sql-server

我有两个表,A1存储标准描述映射,B1存储每个标准的值。我想要一个查询(结果查询)到B1表,其中包含来自A1映射的列别名,如下图所示

enter image description here

3 个答案:

答案 0 :(得分:1)

我建议你改变表格的设计。这是存储数据的不好方法,它不遵循规范化规则。您需要有另一个联结表来存储rownum的CR值。

无论如何,如果你需要为这些表写查询,那么将A1表连接到B1表3次并从那里得到descr。

UPDATE(也使用@gotqn回答中的PIVOT查询):

正如你所说,可能会有很多CR *列...我讨厌游标,但是你需要它:

DECLARE @columnName VARCHAR(200),
        @query VARCHAR(8000) = 'SELECT b.rownum ',
        @joins VARCHAR(8000) = '',
        @tmpColumnValue VARCHAR(100);
DECLARE @getDescr CURSOR
SET @getDescr = CURSOR FOR
select name
from sys.columns where object_name(object_id) = 'B1' ANd name like 'CR%'
OPEN @getDescr
FETCH NEXT
FROM @getDescr INTO @columnName
WHILE @@FETCH_STATUS = 0
BEGIN
    SELECT @tmpColumnValue = pr_desc FROM A1 WHERE pr_id = @columnName;
    SET @query = @query + ', b.' + @columnName + ' AS ' + @tmpColumnValue;
PRINT @columnName
FETCH NEXT
FROM @getDescr INTO @columnName
END
CLOSE @getDescr
DEALLOCATE @getDescr

SET @query = @query + ' FROM B1 b ';
EXECUTE (@query)

使用PIVOT查询:

 DECLARE @Descriptions VARCHAR(MAX);
 DECLARE @columns VARCHAR(MAX);
    SELECT @Descriptions = STUFF
    (
        (
        SELECT ',[' + [pr_desc] + ']'
        FROM A1
        FOR XML PATH(''), TYPE
        ).value('.', 'NVARCHAR(MAX)')
        ,1
        ,1
        ,''
    )

        SELECT @columns = STUFF
    (
        (
        SELECT ',[' + [name] + ']'
        FROM sys.columns
        WHERE object_name(object_id) = 'B1' ANd name like 'CR%'
        FOR XML PATH(''), TYPE
        ).value('.', 'NVARCHAR(MAX)')
        ,1
        ,1
        ,''
    )

  SET @query = '
    SELECT *
    FROM
    (
        SELECT [rownum]
              ,[value]
              ,[pr_desc]
        FROM B1
        UNPIVOT 
        (
            [value] FOR [column] IN (' + @columns + ')
        ) PVT
        INNER JOIN A1 DS
            ON PVT.[column] = DS.[pr_id]
    ) PVT
    PIVOT
    (
        MAX([value]) FOR [pr_desc] IN (' + @Descriptions + ')
    ) PVT;
    ';


EXEC (@query)

答案 1 :(得分:1)

在T-SQL的上下文中,可以按照以下步骤完成:

  1. 无人值守数据

    DECLARE @A1 TABLE
    (
        [pr_id] CHAR(3)
       ,[pr_desc] VARCHAR(12)
    );
    
    
    DECLARE @B1 TABLE
    (
        [rownum] TINYINT
       ,[name] VARCHAR(12)
       ,[Date] DATE
       ,[CR1] INT
       ,[CR2] INT
       ,[CR3] INT
    );
    
    INSERT INTO @A1 ([pr_id], [pr_desc])
    VALUES ('CR1', 'Desc1')
          ,('CR2', 'Desc2')
          ,('CR3', 'Desc3');
    
    INSERT INTO  @B1 ([rownum], [name], [Date], [CR1], [CR2], [CR3])
    VALUES (1, 'Jon', '1/1/2017', 10, 50, 100)
          ,(2, 'Jon', '2/1/2017', 60, 100, 500);
    
    SELECT *
    FROM @B1
    UNPIVOT 
    (
        [value] FOR [column] IN ([CR1], [CR2], [CR3])
    ) PVT;
    

    enter image description here

  2. 加入@A1表格以获取说明:

    SELECT *
    FROM @B1
    UNPIVOT 
    (
        [value] FOR [column] IN ([CR1], [CR2], [CR3])
    ) PVT
    INNER JOIN @A1 DS
        ON PVT.[column] = DS.[pr_id];
    

    enter image description here

  3. 再次调整数据(注意,我们只选择所需的列)

    SELECT *
    FROM
    (
        SELECT [rownum]
              ,[value]
              ,[pr_desc]
        FROM @B1
        UNPIVOT 
        (
            [value] FOR [column] IN ([CR1], [CR2], [CR3])
        ) PVT
        INNER JOIN @A1 DS
            ON PVT.[column] = DS.[pr_id]
    ) PVT
    PIVOT
    (
        MAX([value]) FOR [pr_desc] IN ([Desc1], [Desc2], [Desc3])
    ) PVT;   
    

    enter image description here

  4. 如您所见,为了使用UNPIVOTPIVOT,我们有很多硬编码值。因此,最好使用动态T-SQL。

        CREATE TABLE A1
        (
            [pr_id] CHAR(3)
            ,[pr_desc] VARCHAR(12)
        );
    
    
        CREATE TABLE B1
        (
            [rownum] TINYINT
            ,[name] VARCHAR(12)
            ,[Date] DATE
            ,[CR1] INT
            ,[CR2] INT
            ,[CR3] INT
        );
    
        INSERT INTO A1 ([pr_id], [pr_desc])
        VALUES ('CR1', 'Desc1')
               ,('CR2', 'Desc2')
              ,('CR3', 'Desc3');
    
        INSERT INTO  B1 ([rownum], [name], [Date], [CR1], [CR2], [CR3])
        VALUES (1, 'Jon', '1/1/2017', 10, 50, 100)
              ,(2, 'Jon', '2/1/2017', 60, 100, 500);
    
    
        DECLARE @DynamicTSQLStatement NVARCHAR(MAX);
        DECLARE @Descriptions NVARCHAR(MAX);
    
        SELECT @Descriptions = STUFF
        (
            (
            SELECT ',[' + [pr_desc] + ']'
            FROM A1
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)')
            ,1
            ,1
            ,''
        )
    
        SET @DynamicTSQLStatement = '
        SELECT *
        FROM
        (
            SELECT [rownum]
                  ,[value]
                  ,[pr_desc]
            FROM B1
            UNPIVOT 
            (
                [value] FOR [column] IN ([CR1], [CR2], [CR3])
            ) PVT
            INNER JOIN A1 DS
                ON PVT.[column] = DS.[pr_id]
        ) PVT
        PIVOT
        (
            MAX([value]) FOR [pr_desc] IN (' + @Descriptions + ')
        ) PVT;
        ';
    
        EXEC sp_executesql @DynamicTSQLStatement;
    
        DROP TABLE A1;
        DROP TABLE B1;
    

答案 2 :(得分:0)

你可以使用它。

DECLARE @COLNAMES VARCHAR(4000) = 
    CONVERT(VARCHAR(4000), 
        (SELECT * FROM (VALUES(NULL) ) AS X(DUMY)
            LEFT JOIN B1 ON 1= 0 
                FOR XML RAW, ELEMENTS XSINIL ) ) 

SET @COLNAMES =  
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@COLNAMES,'<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">','')
    , '<DUMY xsi:nil="true"/>','')
    , ' xsi:nil="true"/><',', ') 
    , ', /row>','') 
    , '<','') 

SELECT 
    @COLNAMES = REPLACE(@COLNAMES, pr_id, pr_id + ' ['+ pr_desc+ ']') 
FROM A1

DECLARE @Query NVARCHAR(4000) = 'SELECT ' + @COLNAMES + ' FROM B1'  

PRINT @Query

EXEC sp_executesql @Query

生成的查询:

SELECT rownum, Name, Date, CR1 [Desc1], CR2 [Desc2], CR3 [Desc3] FROM B1

结果:

rownum      Name                                               Date                 Desc1       Desc2       Desc3
----------- -------------------------------------------------- -------------------- ----------- ----------- -----------
1           Jon                                                1/1/2017             10          50          100
2           Jon                                                2/1/2017             60          100         500