【问题标题】:Parsing string data stored all in one column and then pivoting information into separate columns解析存储在一列中的字符串数据,然后将信息旋转到单独的列中
【发布时间】:2020-02-03 04:58:21
【问题描述】:

我正在从一个数据库中提取一份报告,该数据库在一个字符串列中存储了等效的表单。表单每次都有相同的部分标题。我已将这些列标题转换为“|”然后想用它作为分隔符将各自的响应放在单独的列中。我已经完成了枢轴,但随后整个结果在每一列中重复,而不是正确解析。带有最终列标题的示例列文本以粗体 ** 显示。

我觉得我需要更改我的分区语句并包含一个案例,然后更改“|”到 1、2、3 等。

社区卫生工作者初步外展 XYZ 是 48 岁。女性于 99/99/19 联系。 外展原因:作者因 XYZ 而致电 推荐来源: CCM NCM 初始联系/状态:同意注册 已安排 PCP 进行 7 天随访: 您在前往 PCP 办公室的交通方面是否需要帮助:已确定的问题或疑虑:

WITH C AS(

SELECT DISTINCT hnt.note_id, hnt.line,  replace(replace(replace(replace(replace(replace(replace(replace
(note_text, 'CHW Initial Contact/Status:', 'Initial Status'),'Community Health Worker Initial Outreach', '|'), 'Reason for Outreach:', '|')
, 'Referral Source:', '|'), 'Initial Contact/Status:', '|'), 'Was 7 day follow-up with PCP scheduled:','|'),'Do you need assistance with transportation to the PCP office:','|'),
'Identified Issues or Concerns:','|') as field  , row_number () over (partition by hnt.note_id order by hnt.contact_date desc) rn        
From hno_note_text hnt
inner join       note_smartphrase_ids    nsi on hnt.NOTE_CSN_ID = nsi.NOTE_CSN_ID

CROSS APPLY string_split(replace(replace(replace(replace(replace(replace(replace(replace
(note_text, 'CHW Initial Contact/Status:', 'Initial Status'),'Community Health Worker Initial Outreach', '|'), 'Reason for Outreach:', '|')
, 'Referral Source:', '|'), 'Initial Contact/Status:', '|'), 'Was 7 day follow-up with PCP scheduled:','|'),'Do you need assistance with transportation to the PCP office:','|'),
'Identified Issues or Concerns:','|') , '|')    as separated
where smartphrases_id = '151325'    and hnt.line = '1' 
)
SELECT  note_id,
 [1] AS Initial_Outreach
      ,[2] AS Reason
      ,[3] AS RefSource
      ,[4] AS Contact_Status
      ,[5] AS SevenDay
      ,[6] AS Transportation
      ,[7] AS Issues
FROM C
PIVOT(
    MAX(field)
    FOR RN IN([1],[2],[3],[4],[5],[6],[7])  
) as PVT

--根据建议的更改,将代码修改为(我不知道为什么修改后的代码的最后一部分没有显示!):

DECLARE @mockupTable TABLE(ID varchar(254), YourString VARCHAR(MAX));
INSERT INTO @mockupTable 
select distinct hnt.note_id, note_text
From hno_note_text hnt
inner join note_smartphrase_ids nsi on hnt.NOTE_CSN_ID = nsi.NOTE_CSN_ID
where smartphrases_id = '151325'    and hnt.line = '1' 

SELECT  *
FROM @mockupTable t

CROSS APPLY(SELECT CONCAT('{'
,REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(t.YourString
,'Community Health Worker Initial Outreach','"Initial_Outreach":"')
,'Reason for Outreach:','","Reason":"')
,'Referral Source:','","RefSource":"')
,'Was 7 day follow-up with PCP scheduled:','","SevenDay":"')
,'Do you need assistance with transportation to the PCP                     office:','","Transportation":"')
,' Identified Issues or Concerns:','","Issues":"'), 'ACO PRAPARE Screening  Questionnaire','","PRAPARE":"'),
'Next Steps:','","Next Step":"')
,'"}')) A(CastedToJSON)
CROSS APPLY OPENJSON(A.CastedToJSON)
WITH(Initial_Outreach VARCHAR(MAX)
,Reason VARCHAR(MAX)
,RefSource VARCHAR(MAX)
,SevenDay VARCHAR(MAX)
,Transportation VARCHAR(MAX)
,Issues VARCHAR(MAX)
,Prapare VARCHAR(MAX)
,NextSteps VARCHAR(MAX)
) B;

【问题讨论】:

  • 通常对于这样的 SQL 问题,显示原始数据的小样本(如果敏感,则使用虚假值)以及您希望它的样子会很有帮助。也有助于了解您正在使用的 SQL 的风格。谢谢。
  • 谢谢。根据要求更新了描述。使用 SSMS 2016
  • SQL-Server 的哪个版本?

标签: sql-server tsql pivot


【解决方案1】:

使用 SQL-Server 2016(您使用 SSMS 2016 发表评论)我建议沿着 JSON 路线走:

DECLARE @mockupTable TABLE(ID INT IDENTITY, YourString NVARCHAR(MAX));
INSERT INTO @mockupTable VALUES(N'Community Health Worker Initial Outreach XYZ is an 48 y.o. female contacted on 99/99/19. Reason for Outreach: This writer called due to XYZ Referral Source: CCM NCM Initial Contact/Status: Agreed to Enrollment Was 7 day follow-up with PCP scheduled: NO Do you need assistance with transportation to the PCP office: No Identified Issues or Concerns:')

SELECT *
FROM @mockupTable t
CROSS APPLY(SELECT CONCAT('{'
                         ,REPLACE(
                          REPLACE(
                          REPLACE(
                          REPLACE(
                          REPLACE(
                          REPLACE(
                          REPLACE(t.YourString
                                 ,'Community Health Worker Initial Outreach','"Initial_Outreach":"')
                                 ,'Reason for Outreach:','","Reason":"')
                                 ,'Referral Source:','","RefSource":"')
                                 ,'Initial Contact/Status:','","Contact_Status":"')
                                 ,'Was 7 day follow-up with PCP scheduled:','","SevenDay":"')
                                 ,'Do you need assistance with transportation to the PCP office:','","Transportation":"')
                                 ,'Identified Issues or Concerns:','","Issues":"')
                         ,'"}')) A(CastedToJSON)
CROSS APPLY OPENJSON(A.CastedToJSON)
            WITH(Initial_Outreach NVARCHAR(MAX)
                ,Reason NVARCHAR(MAX)
                ,RefSource NVARCHAR(MAX)
                ,Contact_Status NVARCHAR(MAX)
                ,SevenDay NVARCHAR(MAX)
                ,Transportation NVARCHAR(MAX)
                ,Issues NVARCHAR(MAX)
                ) B;

中间的 JSON 看起来像这样:

{
    "Initial_Outreach": " XYZ is an 48 y.o. female contacted on 99/99/19. ",
    "Reason": " This writer called due to XYZ ",
    "RefSource": " CCM NCM ",
    "Contact_Status": " Agreed to Enrollment ",
    "SevenDay": " NO ",
    "Transportation": " No ",
    "Issues": ""
}

简而言之:

  • 我们使用一些字符串方法将您的字符串转换为 JSON 字符串
  • 我们使用OPENJSON 进入 JSON 和
  • 我们使用WITH-clause 在列中返回结果(隐式旋转)

提示:结果可能需要一些修整...

【讨论】:

  • @agalgay 如下...?
  • 抱歉....在原始帖子中发布了修改后的代码
  • @agalgay,啊,我明白了......只是一个提示:我稍微更正了我的答案,你引用的代码不是最后一个......还有一个:这不是如何所以有效。无需填写问题的答案。问题是——嗯——一个问题,答案是可能的解决方案。非常感谢您说谢谢,但如果此答案解决了您的问题,勾选验收检查会更好。一旦你自己达到 15 分,你就会被要求额外投票。这有助于未来的研究人员找到答案,这就是如何在 SO 上说 Thx。快乐编码
  • Yours 使用这些值,但我的值来自 select 语句。当我用 select 语句替换你的 values 子句时,我收到以下错误:只有在使用列列表并且 IDENTITY_INSERT 为 ON 时才能指定表“@mockupTable”中标识列的显式值。
  • @agalgay,你搞错了。我的表@mockupTable 只是为了创建一个独立 示例来模拟您的问题。你根本不需要这个。您必须以某种方式采用我的代码,将@mockupTable 替换为您的真实表名,并且所有列名都相同。无需将您的值转移到我的 mockup 场景中...作为捷径,您可以在我的ID 声明中删除IDENTITY 之后的@mockupTable。这样做可能足以将我的VALUES 替换为您的SELECT...
【解决方案2】:

我采取了稍微不同的方法:

声明@mocktable 表(字段 varchar(2000)) 插入@mocktable

select distinct replace(replace(replace(replace(replace(replace(replace(replace(replace(replace
(note_text, 'CHW Initial Contact/Status:', 'Initial Status'),'Community Health Worker Initial Outreach', '|'), 'Reason for Outreach:', '|')
, 'Referral Source:', '|'), 'Initial Contact/Status:', '|'), 'Was 7 day follow-up with PCP scheduled:','|'),'Do you need assistance with transportation to the PCP office:','|'),
'Identified Issues or Concerns:','|'), 'ACO PRAPARE Screening Questionnaire','|'),
 'Next Steps:','|') as field 
From hno_note_text hnt
inner join note_smartphrase_ids nsi on hnt.NOTE_CSN_ID = nsi.NOTE_CSN_ID
 where smartphrases_id = '151325'   and hnt.line = '1' 
select a.*, b.* from @mocktable   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)')))
,Pos9 = ltrim(rtrim(xDim.value('/x[9]','varchar(max)')))
From  (Select Cast('<x>' + replace((Select replace(field,'|','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml) as xDim) as B1
) B

【讨论】:

  • 只是一个警告:这取决于所有预期字段的排序顺序和存在。不同的顺序或缺少的元素会破坏它...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-26
  • 2017-09-27
  • 2023-03-29
  • 2015-05-13
相关资源
最近更新 更多