SQL-如何从表的XML字段中提取多个属性

如何解决SQL-如何从表的XML字段中提取多个属性

我正在尝试在一个表上运行SQL查询,该表具有一个包含XML数据的字段,但是该XML包含多个值,这些值需要转换为一个字段。请注意,该字段是XML内容,但实际的字段类型设置为nvarchar(max),而不是xml。

编辑:版本为 SQL Server 2014 Express Edition

我有一个这样的表: [有市场的客户清单]

enter image description here

我想在同一行(以逗号分隔)中提取“ marketCode”值:

|CompanyCode|CompanyName|MarketCode,MarketCode,etc.|Phone|

示例的预期输出(请参见屏幕截图):

|ABC123|JOHN DEERE|AA,BB,CC,DD|555-123-000|
|DEF456|NEW HOLLLAND|AA,FF,GG,HH,KK|555-456-0000|

解决方法

样本数据

请下次提供文字而不是图片;-)

Markets被定义为nvarchar(max)。数据以unicode(带有N前缀)插入。

create table Company2
(
    Code nvarchar(6),Name nvarchar(11),Markets nvarchar(max),Phone nvarchar(12)
);

insert into Company2 (Code,Name,Markets,Phone) values
(N'ABC123',N'JOHN DEERE',N'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <license>
    <company companyCode="ABC123">
      <markets>
        <market marketCode="AA"/>
        <market marketCode="BB"/>
        <market marketCode="CC"/>
        <market marketCode="DD"/>
      </markets>
    </company>
  </license>',N'555-123-0000'),(N'DEF456',N'NEW HOLLAND',N'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <license>
    <company companyCode="DEF456">
      <markets>
        <market marketCode="AA"/>
        <market marketCode="FF"/>
        <market marketCode="GG"/>
        <market marketCode="HH"/>
        <market marketCode="KK"/>
      </markets>
    </company>
  </license>',N'555-456-0000');

解决方案

无法将Markets直接投射到XML,因为nvarchar(max)编码与数据中的“ utf-8”冲突。我将转换移动到一个单独的公用表表达式(CTE,cte_convert)中,从nvarchar(max)varchar(max)XML

下一个CTE(cte_parse)现在可以使用c.MarketsXML.nodes()从XML提取<market>节点到新列m.Market中。从该列中提取@marketCode属性作为所需值。

然后使用带有for xml path('')的子查询来连接值。

with cte_convert as
(
    select c.Code,c.Name,convert(XML,convert(varchar(max),c.Markets)) as MarketsXML,c.Phone
    from Company2 c
),cte_parse as
(
    select c.Code,m.Market.value('@marketCode','nvarchar(10)') as MarketCode,c.Phone
    from cte_convert c
    outer apply c.MarketsXML.nodes('/license/company/markets/market') as m(Market)
)
select  cp.Code,cp.Name,stuff(( select ',' + cp2.MarketCode as MC
                from cte_parse cp2
                where cp2.Code = cp.Code
                for xml path(''),type).value('.','nvarchar(max)'),1,'') as MarketCodes,cp.Phone
from cte_parse cp
group by cp.Code,cp.Phone;

结果

Code   Name        MarketCodes    Phone
------ ----------- -------------- ------------
ABC123 JOHN DEERE  AA,BB,CC,DD    555-123-0000
DEF456 NEW HOLLAND AA,FF,GG,HH,KK 555-456-0000

此原始解决方案使用了string_agg()函数,该函数从SQL Server 2017开始可用。

样本数据

注释:Markets列被定义为XML以反映其内容。

create table Company
(
    Code nvarchar(6),Markets XML,Phone nvarchar(12)
);

insert into Company (Code,Phone) values
('ABC123','JOHN DEERE','<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <license>
    <company companyCode="ABC123">
      <markets>
        <market marketCode="AA"/>
        <market marketCode="BB"/>
        <market marketCode="CC"/>
        <market marketCode="DD"/>
      </markets>
    </company>
  </license>','555-123-0000'),('DEF456','NEW HOLLAND','<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <license>
    <company companyCode="DEF456">
      <markets>
        <market marketCode="AA"/>
        <market marketCode="FF"/>
        <market marketCode="GG"/>
        <market marketCode="HH"/>
        <market marketCode="KK"/>
      </markets>
    </company>
  </license>','555-456-0000');

解决方案

with cte_parse as
(
    select c.Code,c.Phone
    from Company c
    outer apply c.Markets.nodes('/license/company/markets/market') as m(Market)
)
select cp.Code,string_agg(cp.MarketCode,',') as MarketCodes,cp.Phone;

Fiddle

,
declare @t table(CompanyMarkets nvarchar(max));
insert into @t(CompanyMarkets)
values(N'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<license>
<company companyCode="ABC123">
<markets>
<market marketCode="AA"/>
<market marketCode="BB"/>
<market marketCode="CC"/>
<market marketCode="DD"/>
</markets>
</company>
</license>');

select
    --remove encoding ...
    try_cast(replace(CompanyMarkets,'encoding="UTF-8"','') as xml),--... or transform any prolog to a weird&harmless processing instruction 
    try_cast(concat(case when CompanyMarkets like N'<?xml%' then '<?x ' end,CompanyMarkets) as xml) 
from @t;


select *,try_cast(concat(case when CompanyMarkets like N'<?xml%' then '<?x ' end,CompanyMarkets) as xml).query('
    for $i in (data(/license/company/markets/market/@marketCode)[1],(for $k in data(/license/company/markets/market/@marketCode)[position()>1] return concat(",",$k)))
    return text {$i}
    ').value('.',--?? no spaces in marketCodes
    replace(
    try_cast(concat(case when CompanyMarkets like N'<?xml%' then '<?x ' end,CompanyMarkets) as xml).query('data(/license/company/markets/market/@marketCode)').value('.',' ','),stuff(
    try_cast(concat(case when CompanyMarkets like N'<?xml%' then '<?x ' end,CompanyMarkets) as xml).query('
    for $i in data(/license/company/markets/market/@marketCode) return text {concat(",$i)}
    ').value('.','')

from @t;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-