【问题标题】:How to split a single column value into multiple columns with value as column names using SQL query如何使用 SQL 查询将单个列值拆分为多个列,并将值作为列名
【发布时间】:2020-10-06 19:33:23
【问题描述】:

我正在尝试将值从单个列获取到多个列中,并将值作为字段名称。我见过许多与此类似的不同问题,因此尝试了所有选项,但没有任何帮助。

例如,

Details Field value: FirstName:John|LastName:Mike|DateOfBirth:09/09/1980|Department:IT|

预期如下,

Create table Employee(Details varchar(200), [address] varchar(50), Status# int)

insert into Employee(Details,[address], [Date] )
values ('FirstName:John|LastName:Mike|DateOfBirth:09/09/1980|Department:IT|', '344 5th cross st, MA', CURRENT_TIMESTAMP)
insert into Employee(Details,[address], [Date] )
values ('FirstName:Sarah|LastName:Jones|DateOfBirth:10/09/1970|Department:Admin', '444 8th avenue, PA', CURRENT_TIMESTAMP)

我的查询

select address,  
  left(Details,charindex('|',Details)-1) as FirstName,
  substring(Details,charindex('|',Details)+1,len(Details)) as LastName  
from 
  Employee  

这就是我的查询得到的结果

【问题讨论】:

  • 真正的解决方案是修复你的数据模型。

标签: sql sql-server string


【解决方案1】:

这是一个选项,前提是您的字符串布局是一致的。

示例

Select A.Address 
      ,FirstName   = Pos2
      ,LastName    = Pos4
      ,DateOfBirth = try_convert(date,Pos6)
      ,Department  = Pos8
  From Employee A
  Cross Apply (
                Select Pos1 = trim(JSON_VALUE(S,'$[0]'))  -- Could be reduced to 2,4,6 & 8
                      ,Pos2 = trim(JSON_VALUE(S,'$[1]'))
                      ,Pos3 = trim(JSON_VALUE(S,'$[2]'))
                      ,Pos4 = trim(JSON_VALUE(S,'$[3]'))
                      ,Pos5 = trim(JSON_VALUE(S,'$[4]'))
                      ,Pos6 = trim(JSON_VALUE(S,'$[5]'))
                      ,Pos7 = trim(JSON_VALUE(S,'$[6]'))
                      ,Pos8 = trim(JSON_VALUE(S,'$[7]'))
                 From  ( values ( '["'+replace(replace(replace(Details,':','|'),'"','\"'),'|','","')+'"]' ) ) A(S)
              ) B

退货

Address                 FirstName   LastName    DateOfBirth   Department
344 5th cross st, MA    John        Mike        1980-09-09    IT
444 8th avenue, PA      Sarah       Jones       1970-10-09    Admin

编辑 - XML 版本

Select A.Address 
      ,FirstName   = Pos2
      ,LastName    = Pos4
      ,DateOfBirth = try_convert(date,Pos6)
      ,Department  = Pos8
  From Employee A
  Cross Apply (
                Select Pos1 = ltrim(rtrim(xDim.value('/x[1]','varchar(max)')))
                      ,Pos2 = ltrim(rtrim(xDim.value('/x[2]','varchar(max)')))
                      ,Pos3 = ltrim(rtrim(xDim.value('/x[3]','varchar(max)')))
                      ,Pos4 = ltrim(rtrim(xDim.value('/x[4]','varchar(max)')))
                      ,Pos5 = ltrim(rtrim(xDim.value('/x[5]','varchar(max)')))
                      ,Pos6 = ltrim(rtrim(xDim.value('/x[6]','varchar(max)')))
                      ,Pos7 = ltrim(rtrim(xDim.value('/x[7]','varchar(max)')))
                      ,Pos8 = ltrim(rtrim(xDim.value('/x[8]','varchar(max)')))
                From  (Select Cast('<x>' + replace((Select replace(replace(A.Details,':','|'),'|','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml) as xDim) as A 
              ) B

【讨论】:

  • 感谢您的帮助@John。非常感谢。不幸的是,我使用的是 SSMS 2014 版本,因此它会为 try_convert 和 Json_Value 内置函数抛出错误。
  • @Uba 还有一种 XML 方法。看看stackoverflow.com/questions/43789578/…
  • @Uba 查看 XML 版本的编辑
【解决方案2】:

这是使用动态 sql 和几个 REPLACE() 函数的更简单方法...

DECLARE 
    @string nvarchar(4000) = N'FirstName:John|LastName:Mike|DateOfBirth:09/09/1980|Department:IT|',
    @d_sql nvarchar(4000) = N'',
    @debug bit = 0;

SELECT @d_sql = CONCAT('SELECT [',
    REPLACE(REPLACE(TRIM('|' FROM @string), ':', '] = '''), '|', ''', ['), ''';'
    );

IF @debug = 1
BEGIN 
    PRINT(@d_sql);
END;
ELSE 
BEGIN 
    EXEC sys.sp_executesql @d_sql;
END;

生成的 SQL 最终看起来像这样 (@debug = 1)...

SELECT [FirstName] = 'John', [LastName] = 'Mike', [DateOfBirth] = '09/09/1980', [Department] = 'IT';

这又会产生以下结果 (@debug = 0)...

FirstName LastName DateOfBirth Department
--------- -------- ----------- ----------
John      Mike     09/09/1980  IT

【讨论】:

    猜你喜欢
    • 2011-07-04
    • 1970-01-01
    • 1970-01-01
    • 2018-10-12
    • 2016-01-11
    • 2018-01-15
    • 1970-01-01
    • 2018-10-07
    • 2021-02-06
    相关资源
    最近更新 更多