SQLServer 2005 XML 在 T-SQL 查询中的典型应用[转]
前言:
此文只讲xml数据类型及相应的一些操作方法在解决日常T-SQL编程中的一些应用,而避开xml modify,xml schema,xml索引,命名空间等这些语法性或者生硬的一些问题(这些语法您可以查联机丛书),即此文主要讲以xml的一些操作特性及xquery去解决编程问题.
Tags:
xquery ,FLWOR迭带 ,sql:column ,sql:variable ,nodes ,value ,query ,xpath ,xquery function, if, 聚合函数, xs:function等
典型应用举例:
--====================================================================
--拆分
DECLARE @s VARCHAR(100)
SET @s='a,b,c,dd,ee,f,aa,a,aa,f'
--常规做法(sql2000常用),以一split函数拆分串为表类型结构,如
--SELECT * FROM dbo.split(@s,',') a
--当然,也可能是循环去拆分,或者以一输助表的identity列利用charindex等函数拿identity列值与','的位置匹配实现拆分
--这些做法,roy_88及本人以前都整理过,不再累赘,可见推荐贴。即便 是xml法,也贴过多次,下面一笔带过
--XML做法:
SELECT b.v FROM
(SELECT CAST('<r>' + REPLACE(@s,',','</r><r>') + '</r>' AS XML) x) a --将字串","换换为"</r><r>"并前后拼上<r>,</r>以用来构造xml串
CROSS APPLY
(SELECT v=t.x.value('.','VARCHAR(10)') FROM a.x.nodes('//r') AS t(x) ) b --使用 xml.nodes函数将xml串拆分为行
/*
a
b
c
dd
ee
f
aa
a
aa
f
*/
--(2)
--====================================================================
--去重,@s中出现的元素,重复的只要一个,希望结果为 'a,b,c,dd,ee,f'
--常规做法,循环或函数,或临时表拆后distinct
--XML做法:
--a.在(1)的基础上进行
;WITH fc AS --定义cte命名,将@s转换为一个表结构
(
SELECT DISTINCT b.v v
FROM
(SELECT CAST('<r>' + REPLACE(@s,',','</r><r>') + '</r>' AS XML) x) a
CROSS APPLY
(SELECT v=t.x.value('.','VARCHAR(10)') FROM a.x.nodes('//r') AS t(x) ) b
)
--对这个表利用xml方法进行行值拼接
SELECT STUFF(b.v.value('/r[1]','varchar(100)'),1,1,'')
FROM
(SELECT v=(SELECT ',' + v FROM fc FOR XML PATH(''),ROOT('r'),TYPE)) b
/*
a,aa,b,c,dd,ee,f
*/
--b FLWOR语句 + T-SQL组合:
SELECT STUFF(v,1,1,'') FROM
(SELECT CAST('<r>' + REPLACE(@s,',','</r><r>') + '</r>' AS XML) x) a
CROSS APPLY
(SELECT x=(SELECT t.x.value('.','varchar(10)') v,idx=ROW_NUMBER() OVER(ORDER BY GETDATE()) FROM a.x.nodes('//r') AS t(x) FOR XML PATH('r'),TYPE)) b --利用row_number得到唯一idx
CROSS APPLY
(SELECT v=CAST(b.x.query('for $r in //r where count(//r[v=$r/v and idx<$r/idx])=0 return concat(",",xs:string($r/v[1]))') AS VARCHAR(MAX))) c --类似count计数法,取得v相同的节点集idx值最小的节点,原型为:
--SELECT * FROM tb a WHERE 1>(SELECT COUNT(*) FROM tb WHERE v=a.v AND id<a.id)
/*
a ,b ,c ,dd ,ee ,aa ,f
*/
--c distinct-values
SELECT REPLACE(v,' ',',') FROM
(SELECT CAST('<r>' + REPLACE(@s,',','</r><r>') + '</r>' AS XML) x) a
CROSS APPLY
(SELECT CAST(a.x.query('distinct-values(//r)') AS VARCHAR(MAX)) v) b --直接调用distinct-values函数来操作
/*
a,b,c,dd,ee,f,aa
*/
-- 导入去重, last() , position()
DECLARE @doc xml
SET @doc ='<?xml version="1.0" encoding="gb2312" ?>
<employees>
<employee>
<empid>e0001</empid>
<name>萧峰</name>
</employee>
<employee>
<empid>e0002</empid>
<name>段誉</name>
</employee>
<employee>
<empid>e0003</empid>
<name>王语嫣</name>
</employee>
<employee>
<empid>e0003</empid>
<name>张无忌</name>
</employee>
</employees>
'
create table people2
(
personid varchar(10) primary key ,
name varchar(20)
)
INSERT people2
SELECT DISTINCT b.* FROM
(SELECT x = @doc.query('for $e in //employee return //employee[empid = $e/empid][last()]')) a --FLWOR时,用当前节点去//emploee节点集中找节点集中empid等于当前节点的empid, 在找到的集合中取最后一个利用last()函数
CROSS APPLY
(SELECT id=t.x.value('empid[1]','varchar(100)'),name=t.x.value('name[1]','varchar(100)') FROM a.x.nodes('//employee') AS t(x)) b
SELECT * FROM people2
/*
e0001 萧峰
e0002 段誉
e0003 张无忌
*/
GO
drop table people2
GO
--同组一选多,也可应用此方法,不过没有必要,就不再累赘了。
--(3)
--====================================================================
--列名,列值相关
--a,按行聚合
declare @t table(Sname nvarchar(5), V1 float, V2 float, V3 float, V4 float, V5 float, V6 float)
insert @t select N'张三', 0.11 , 0.21 , 0.29, 0.32 , 0.11, 0.08
insert @t select N'李四', 0.01 , 0.61 , 0.21, 0.73 , 0.21, 0.12
insert @t select N'张五', 0.31 , 0.21 , 0.23, 0.33 , 0.91, 0.65
insert @t select N'张六', 0.59 , 0.11, 0.26, 0.13, 0.01, 0.15
select b.* from
(select x=cast((select * from @t for xml path('r')) as xml)) a
cross apply
(
select name=x.query('./Sname/text()'),v=x.query('max(./*[local-name(.)!="Sname"])') from a.x.nodes('//r') as t(x)
--r为二级节点(因为文档本身无根节点,即为每项的顶级节点)即为一个r节点表示一条记录. r下级节点,每个表示一个列,因为列名未知,所以用/*匹配所有节点,因为name为区别列,不参与聚合运算,故用local-name取得来过滤
) b
/*
张三 0.32
李四 0.73
张五 0.91
张六 0.59
*/
--b ,由值引到取列
if not object_id('T1') is null
drop table T1
GO
Create table T1([tId] int,[tName] nvarchar(4))
Insert T1
select 1,N'zhao' union all
select 2,N'qian' union all
select 3,N'sun'
Go
--> --> 借且(Roy)生成測試數據
if not object_id('T2') is null
drop table T2
Go
Create table T2([tId] int,[zhao] nvarchar(1),[qian] nvarchar(1),[sun] nvarchar(1))
Insert T2
select 1,N'a',N'b',N'c' union all
select 2,N'd',N'e',N'f' union all
select 3,N'g',N'h',N'i'
Go
SELECT c.tid,c.tName,v FROM t1 c
CROSS APPLY
(SELECT x=(SELECT * FROM t2 WHERE tid=c.tid FOR XML PATH('r'),TYPE)) a
CROSS APPLY
(SELECT v=t.x.query('./*[local-name(.)=xs:string(sql:column("c.tName")) ]/text()')
FROM a.x.nodes('//r') AS t(x)
) b
/*
1 zhao a
2 qian e
3 sun i
*/
--c, 列名,列值,与系统表
CREATE TABLE tb(f1 INT,f2 INT,x INT,z INT,d INT,ex INT,dd INT,vv INT)
INSERT tb SELECT 1,2,3,5,11,3,2423,33
GO
SELECT * FROM tb
GO
SELECT name,v FROM
( SELECT name FROM sys.columns WHERE object_id=object_id('tb','u') ) a
CROSS JOIN
(SELECT x=(SELECT * FROM tb FOR XML PATH('r'),TYPE)) b
CROSS APPLY
(SELECT v=t.x.query('./*[local-name(.)=xs:string(sql:column("a.name")) ]/text()') FROM b.x.nodes('//r') AS t(x) ) c
/*
f1 1
f2 2
x 3
z 5
d 11
ex 3
dd 2423
vv 33
*/
GO
DROP TABLE tb
GO
--(4)
--一些综合计算
--以下表 ta.a值 yyyymmdd-yyyymmdd表连续时间段,","表单个日期
If object_id('ta','u') is not null
Drop table ta
Go
Create table ta(a varchar(100))
Go
Insert into ta
select '1 ¦ ¦20080101-20080911'
union all
select '2 ¦ ¦20080101,20080201,20080301,20080515,20080808'
union all
select '3 ¦ ¦20080101,20080201,20080301,20080515,20081108'
Go
declare @s varchar(8)
select @s= convert(varchar(8),getdate(),112)
select stuff(replace(replace(cast(x as varchar(1000)),'</item><item>',case when type='1' then '-' else ',' end),'</item>',''),1,6,type + ' ¦ ¦') a
from
(
select left(a,1) type,
cast(
'<item>'
+
replace(
stuff(a,1,5,''),
case when left(a,1)=1 then '-' else ',' end,
'</item><item>'
)
+
'</item>'
AS XML
) x
from ta
) base
where x.value('
if (sql:column("base.type")="1") then
if(
(/item/text())[1]<sql:variable("@s")
and
(/item/text())[2]>sql:variable("@s")
)
then 1
else 0
else
count(//item[text()>sql:variable("@s")])
'
,
'int'
)>0
go
待续。。
来源:http://blog.csdn.net/fcuandy/article/details/3248618
SQLServer 2005 XML 在 T-SQL 查询中的典型应用[转]相关推荐
- oracle查数据存入数组,如何在SQL查询中使用Oracle关联数组
ODP.Net公开了将关联数组作为参数从C#传递到Oracle存储过程的能力.除非您尝试在sql查询中使用该关联数组中包含的数据,否则它是一个很好的功能. 原因是它需要上下文切换 – SQL语句需要S ...
- SQL查询中having和where的异同点
SQL查询中having与where 的异同点 在sql查询中, having与where类似,可以筛选数据,where后的表达式怎么写,having后就怎么写. 1. where针对表中的列发挥作用 ...
- Laravel SQL查询中first、pluck、lists方法的使用
Laravel SQL查询中first.pluck.lists方法的使用
- 读书笔记:SQL 查询中的SQL*Plus 替换变量(DEFINE变量)和参数
本文为"SQL*Plus 替换变量 - 在 SQL 查询中定义变量和参数"的读书笔记. 此文主要是讲替换变量,也称为DEFINE变量,但也涉及了绑定变量和SQL Plus系统变量. ...
- vba ado 执行多条mysql 语句,Excel VBA+ADO+SQL入门教程003:SQL查询中字段技巧的总结...
原标题:Excel VBA+ADO+SQL入门教程003:SQL查询中字段技巧的总结 本章概要: 1,几个概念 1.1, 数据库和Excel工作簿 1.2,数据表和Excel工作表 1.3,记录.字段 ...
- mysql and 和where,关于mysql:连接sql查询中where和and子句的区别
本问题已经有最佳答案,请猛点这里访问. 下面两个SQL查询有什么区别 和 号 根据以下两个测试结果 速度更快(237比460).据我所知,这是一个标准. . 氧化镁 不,有细微的差别,你不能说没有差别 ...
- sql查询中使用in和exits比较和区别
首先,查询中涉及到的两个表,一个user和一个order表,具体表的内容如下: user表: order表: in 确定给定的值是否与子查询或列表中的值相匹配.in在查询的时候,首先查询子查询的表,然 ...
- java sql 查询中的转义序列不对_在 JDBC 中使用 SQL 转义序列 - SQL Server | Microsoft Docs...
使用 SQL 转义序列Using SQL escape sequences 08/12/2019 本文内容 按照 JDBC API 的定义,Microsoft JDBC Driver for SQL ...
- sql查询中截取字符串
SQL 语句中查询结果字符截取left,right,substrng用法 在SQL的实际用途中,经常会碰到需要对查询结果值需要做字段的一些截取,下面列举经常用到的三种常用截取方式. 1.LEFT(st ...
最新文章
- 算法实现太难了?机器学习也需要开源软件
- 【React自制全家桶】一、Webstrom+React+Ant Design+echarts搭建react项目
- centos7 VNC-Server-6.7.2
- POI:根据单元格的自定义名获取单元格的位置
- HTTP GET与POST区别
- Android JNI开发系列(二)HelloWorld
- php怎么关闭oracle连接,PHP 连接 Oracle
- mysql订单详情的设计_订单功能模块设计与实现
- linux find prune文件,Linux中find命令-path -prune用法详解
- Tensorflow CUDA及CUDNN版本对应关系表查询
- java dns 缓存_一次排查多线程引发Java DNS缓存的Bug
- Hadoop 各组件介绍
- 华北电力计算机技术考研难度,华北电力大学(专业学位)计算机技术考研难吗
- 【Kubernetes 015】pod调度之Affinity亲和性
- php 长链接生成短链接
- 轻量易用的网站bug与性能监控平台——灵雀应用监控平台
- 沉浸其中,二次元高清图片
- AE生成高清视频设置
- iOS学习笔记12—听筒和扬声器的转换
- html好友页面,好友列表.html
热门文章
- 使用hibernate实现树形结构无限级分类
- java tomcat mysql_java+tomcat+mysql实现登录界面基本思路
- Intel汇编语言程序设计学习-第三章 汇编语言基础-中
- 【Linux 内核】进程管理 ( 进程特殊形式 | 内核线程 | 用户线程 | C 标准库与 Linux 内核中进程相关概念 | Linux 查看进程命令及输出字段解析 )
- 【C 语言】数组 ( 指针退化验证 | 计算数组大小 | #define LENGTH(array) (sizeof(array) / sizeof(*array)) )
- 【Android 热修复】热修复原理 ( 类加载分析 | 分析 PathClassLoader 源码 | 分析 BaseDexClassLoader 源码 | 分析 PathDexList 源码 )
- 【Flutter】Dart 面向对象 ( 类定义 | 类的继承 | 私有变量 | 可选参数 | 默认参数 | 初始化列表 )
- 【Netty】NIO 简介 ( NIO 模型 | NIO 三大组件 | 选择器 Selector | 通道 Channel | 缓冲区 Buffer | NIO 组件分配 | 缓冲区示例 )
- 跟我一起用node-express搭建一个小项目(node连接mongodb)[三]
- Http Tunnel 小记