【问题标题】:SQL Server map rows with columns of different tableSQL Server 用不同表的列映射行
【发布时间】:2019-02-14 21:26:41
【问题描述】:

我正在尝试基于行和列值映射创建结果。这是一个例子

第一个表 (#column_table) 具有 colunm_id 和 column_name。

第二个表#column_value 具有第一个表中的行的值。

我想创建一个如下所示的数据集:

我如何做到这一点?

这里是数据设置的临时表。

create table #column_table (column_id int, column_name varchar(50) )

insert into #column_table
values
(1, 'FirstName'),
(2, 'LastName'),
(3, 'Address'),
(4, 'Phone')


create table #column_value(FirstName varchar(50), LastName varchar(50), Phone varchar(50),)

insert into #column_value
values
('John','Smith','1234567')

select * from  #column_table
select * from #column_value

【问题讨论】:

  • #column_value中是否只有1行?
  • 是的。 #column_value 将只有一行。

标签: sql sql-server tsql sql-server-2016


【解决方案1】:

UNPIVOT 会更高效,但如果您需要更动态的方法而不实际使用动态 SQL

示例

Select  D.Column_ID
       ,Column_Value = C.Value
 From  #column_value A
 Cross Apply (values (convert(xml,(Select A.* For XML Raw)))) B(XMLData)
 Cross Apply (
                Select Item  = xAttr.value('local-name(.)', 'varchar(100)')
                      ,Value = xAttr.value('.','varchar(max)')
                 From  XMLData.nodes('//@*') xNode(xAttr)
             ) C
 Join #column_table D on C.Item=D.Column_Name

退货

Column_ID   Column_Value
1           John
2           Smith
4           1234567

【讨论】:

  • 谢谢约翰。结果正是我想要的。
【解决方案2】:

您可以使用性能更高的 UnPivot 来实现这一点,但正如@JohnCappelleti 所说,您需要实现 Dynamic SQL 逻辑:

旁注:我使用了like '#column_value%' 而不是= '#column_value',因为该示例正在处理临时表。此外,您应该将#column_value#column_table 替换为相应的表名。另外,我使用了tempdb.information_schema,因为临时表存储在tempdb 数据库中。

--Create Tables and insert values
create table #column_table (column_id int, column_name varchar(50) )

insert into #column_table
values
(1, 'FirstName'),
(2, 'LastName'),
(3, 'Address'),
(4, 'Phone')


create table #column_value(FirstName varchar(50), LastName varchar(50), Phone varchar(50),)

insert into #column_value
values
('John','Smith','1234567')

select * from  #column_table
select * from #column_value

--Get columns found in both tables
SELECT t2.column_id,t2.column_name 
INTO #tblTemp
from tempdb.information_schema.columns t1
inner join #column_table t2 on t1.COLUMN_NAME = t2.column_name
where t1.table_name like '#column_value%'

--Building Dynamic Query
DECLARE @strQuery VARCHAR(4000) = 'SELECT * FROM (SELECT '
DECLARE @strUnPivot as varchar(max) = ' UNPIVOT ([Value] for [Column_ID] IN ('
SELECT @strUnPivot = ISNULL(@strUnPivot,'') + '[' + CAST(column_id as varchar(10)) + '] ,' From  #tblTemp
SELECT  @strQuery = @strQuery + '[' + column_name + '] AS "' + CAST(column_id as varchar(10)) + '",' From  #tblTemp

SELECT @strQuery = SUBSTRING(@strQuery,1,LEN(@strQuery) - 1) + ' FROM #column_value)  AS p ' + SUBSTRING(@strUnPivot,1,LEN(@strUnPivot) - 1) + ')) AS unpvt '

--Execute Query
EXEC(@strQuery)

结果

参考文献

【讨论】:

  • 谢谢。这看起来很棒。
【解决方案3】:

使用CASE 和交叉连接:

select 
  ct.column_id,
  case ct.column_id
    when 1 then cv.FirstName
    when 2 then cv.LastName
    when 4 then cv.Phone
  end column_value
from #column_table ct cross join #column_value cv
where ct.column_id <> 3 

demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多