SQL Server:从链接到另一个表的ID列动态创建列

SQL Server:从链接到另一个表的ID列动态创建列,sql,sql-server,sql-server-2008-r2,Sql,Sql Server,Sql Server 2008 R2,我正在尝试根据链接到另一个列名表的ID动态创建列。(我不知道这是否可能用于ssrs报告和网页上的GridView。) 看看下面的例子,“当前表”就是它现在的样子。每个名字我都有一列。我已经创建了定义表。我希望使当前表看起来像建议的表,并使用名称定义表“创建”select或其他内容中的列,使其看起来像现在一样 这是一个非常奇怪的数据结构。这里有一种方法: select d.id as definition, coalesce(c.p1, c.p2, c.p3, c.p4) as "c

我正在尝试根据链接到另一个列名表的ID动态创建列。(我不知道这是否可能用于ssrs报告和网页上的GridView。)

看看下面的例子,“当前表”就是它现在的样子。每个名字我都有一列。我已经创建了定义表。我希望使当前表看起来像建议的表,并使用名称定义表“创建”select或其他内容中的列,使其看起来像现在一样


这是一个非常奇怪的数据结构。这里有一种方法:

select d.id as definition,
       coalesce(c.p1, c.p2, c.p3, c.p4) as "count",
       c.ts
from current_table c join
     definition d
     on (d.name = 'p1' and p1 is not null) or
        (d.name = 'p2' and p2 is not null) or
        (d.name = 'p3' and p3 is not null) or
        (d.name = 'p4' and p4 is not null) ;

这里有一种方法可以“动态地”解压数据,而无需实际使用动态SQL

显然,Gordon's会更有效,但在这里,您不必声明列

示例

Select  D.id
       ,[count] = C.Value
       ,A.ts
 From  CurrentTable A
 Cross Apply ( values (cast((Select A.* for XML RAW) as xml))) B(XMLData)
 Cross Apply (
                Select Item = a.value('local-name(.)','varchar(100)')
                      ,Value = a.value('.','int')    -- Use appropriate type
                 From  B.XMLData.nodes('/row')  as C1(n)
                 Cross Apply C1.n.nodes('./@*') as C2(a)
                 Where a.value('local-name(.)','varchar(100)') not in ('ts','OtherColToExclude')
             ) C
 Join   definition D on C.item=D.Name
返回

id  count   ts
1   5       2018-12-06
2   88      2018-11-01
2   18      2018-10-18
3   32      2018-10-27
4   6       2018-10-27

您也可以尝试使用unpivot来实现您的需求。有关更多详细信息,请参阅本文:

希望它能帮助你

致以最良好的祝愿


Rachel

数据图像对您请求帮助的志愿者没有帮助。样本数据应按原样提供,
text
;或者更好地使用DDL和DML语句。看一看
----drop table [current_table] 
----drop table [definition] 
create table [current_table] 
(p1 int,
p2 int,
p3 int,
p4 int,
ts date )
insert into [current_table] values
(5,null,null,null,'20181206'),
(null,88,null,null,'20181101'),
(null,18,null,null,'20181018'),
(null,null,32,null,'20181027'),
(null,null,null,6,'20181014')

create table [definition] 
(id int,
name varchar(5) )
insert into [definition] values 
(1,'p1'),(2,'p2'),
(3,'p3'),(4,'p4')

;with cte as (
SELECT [name] ,[count],ts 
FROM [current_table]  t
UNPIVOT ([count] FOR [name] IN ([p1],[p2],[p3],[p4])) u)
select b.id,a.count,a.ts from  cte a  join [definition] b on a.name=b.name
/*
id          count       ts
----------- ----------- ----------
1           5           2018-12-06
2           88          2018-11-01
2           18          2018-10-18
3           32          2018-10-27
4           6           2018-10-14
*/


------dynamic-------------
DECLARE @ColNames varchar(1000);
SET @ColNames = '';
SELECT @ColNames =stuff((
    SELECT DISTINCT ',' + QUOTENAME(COLUMN_NAME)
    FROM INFORMATION_SCHEMA.COLUMNS p2
    WHERE TABLE_NAME = 'current_table'
      AND COLUMN_NAME like 'p%'
    FOR XML PATH(''), TYPE).value('.', 'varchar(max)')
            ,1,1,'')
DECLARE @CMD nvarchar(2000);
SET @CMD = ';with cte as (
SELECT [name] ,[count],ts 
FROM [current_table]  t
UNPIVOT ([count] FOR [name] IN ('+@ColNames+')) u)
select b.id,a.count,a.ts from  cte a  join [definition] b on a.name=b.name'
PRINT @CMD
execute sp_executesql @CMD
/*
;with cte as (
SELECT [name] ,[count],ts 
FROM [current_table]  t
UNPIVOT ([count] FOR [name] IN ([p1],[p2],[p3],[p4])) u)
select b.id,a.count,a.ts from  cte a  join [definition] b on a.name=b.name
id          count       ts
----------- ----------- ----------
1           5           2018-12-06
2           88          2018-11-01
2           18          2018-10-18
3           32          2018-10-27
4           6           2018-10-14
*/