加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

SQLServer2005 XML在T-SQL查询中的典型应用

发布时间:2020-12-12 15:46:28 所属栏目:MsSql教程 来源:网络整理
导读:/* SQLServer2005?XML在T-SQL查询中的典型应用 整理:fcuandy 时间:2008.11.7 前言: ????此文只讲xml数据类型及相应的一些操作方法在解决日常T-SQL编程中的一些应用,而避开xml?modify, xml?schema,xml索引,命名空间等这些语法性或者生硬的一些问题(这些语
  1. /*
  2. SQLServer2005?XML在T-SQL查询中的典型应用
  3. 整理:fcuandy
  4. 时间:2008.11.7
  5. 前言:
  6. ????此文只讲xml数据类型及相应的一些操作方法在解决日常T-SQL编程中的一些应用,而避开xml?modify,
  7. xml?schema,xml索引,命名空间等这些语法性或者生硬的一些问题(这些语法您可以查联机丛书),即此文主要
  8. 讲以xml的一些操作特性及xquery去解决编程问题.
  9. Tags:
  10. ????xquery?,FLWOR迭带?,sql:column?,sql:variable?,nodes?,value?,query?,xpath?,xquery?function,?if,?聚合函数,?xs:function等
  11. 典型应用举例:
  12. */
  13. --(1)
  14. --====================================================================
  15. --拆分
  16. DECLARE?@s?VARCHAR(100)
  17. SET?@s='a,b,c,dd,ee,f,aa,a,f'
  18. --常规做法(sql2000常用),以一split函数拆分串为表类型结构,如
  19. --SELECT?*?FROM?dbo.split(@s,',')?a
  20. --当然,也可能是循环去拆分,或者以一输助表的identity列利用charindex等函数拿identity列值与','的位置匹配实现拆分
  21. --这些做法,roy_88及本人以前都整理过,不再累赘,可见推荐贴。即便?是xml法,也贴过多次,下面一笔带过
  22. --XML做法:
  23. SELECT?b.v?FROM
  24. ????(SELECT?CAST('<r>'?+?REPLACE(@s,'</r><r>')?+?'</r>'?AS?XML)?x)?a???--将字串","换换为"</r><r>"并前后拼上<r>,</r>以用来构造xml串
  25. CROSS?APPLY
  26. ????(SELECT?v=t.x.value('.','VARCHAR(10)')?FROM?a.x.nodes('//r')?AS?t(x)?)?b??--使用?xml.nodes函数将xml串拆分为行
  27. /*
  28. a
  29. b
  30. c
  31. dd
  32. ee
  33. f
  34. aa
  35. a
  36. aa
  37. f
  38. */
  39. --(2)
  40. --====================================================================
  41. --去重,@s中出现的元素,重复的只要一个,希望结果为?'a,f'
  42. --常规做法,循环或函数,或临时表拆后distinct
  43. --XML做法:
  44. --a.在(1)的基础上进行
  45. ;WITH?fc?AS???--定义cte命名,将@s转换为一个表结构
  46. (
  47. ????SELECT?DISTINCT?b.v?v
  48. ????????????FROM
  49. ????????????????(SELECT?CAST('<r>'?+?REPLACE(@s,'</r><r>')?+?'</r>'?AS?XML)?x)?a
  50. ????????????CROSS?APPLY
  51. ????????????????(SELECT?v=t.x.value('.','VARCHAR(10)')?FROM?a.x.nodes('//r')?AS?t(x)?)?b
  52. )
  53. --对这个表利用xml方法进行行值拼接
  54. SELECT?STUFF(b.v.value('/r[1]','varchar(100)'),1,'')
  55. ????FROM
  56. ????(SELECT?v=(SELECT?','?+?v?FROM?fc?FOR?XML?PATH(''),ROOT('r'),TYPE))?b
  57. /*
  58. a,f
  59. */
  60. --b?FLWOR语句?+?T-SQL组合:
  61. SELECT?STUFF(v,'')?FROM
  62. ????(SELECT?CAST('<r>'?+?REPLACE(@s,'</r><r>')?+?'</r>'?AS?XML)?x)?a
  63. CROSS?APPLY
  64. ????(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
  65. CROSS?APPLY
  66. ????(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值最小的节点,原型为:
  67. --SELECT?*?FROM?tb?a?WHERE?1>(SELECT?COUNT(*)?FROM?tb?WHERE?v=a.v?AND?id<a.id)
  68. /*
  69. a?,b?,c?,dd?,ee?,aa?,f
  70. */
  71. --c?distinct-values
  72. SELECT?REPLACE(v,'?',')?FROM
  73. ????(SELECT?CAST('<r>'?+?REPLACE(@s,'</r><r>')?+?'</r>'?AS?XML)?x)?a
  74. CROSS?APPLY
  75. ????(SELECT?CAST(a.x.query('distinct-values(//r)')?AS?VARCHAR(MAX))?v)?b??--直接调用distinct-values函数来操作
  76. /*
  77. a,aa
  78. */
  79. --?导入去重,?last()?,?position()
  80. DECLARE???@doc??xml
  81. SET???@doc???='<?xml?version="1.0"?encoding="gb2312"??>
  82. <employees>
  83. ????<employee>
  84. ????????<empid>e0001</empid>
  85. ????????<name>萧峰</name>
  86. ????</employee>
  87. ????<employee>
  88. ????????<empid>e0002</empid>
  89. ????????<name>段誉</name>
  90. ????</employee>
  91. ????<employee>
  92. ????????<empid>e0003</empid>
  93. ????????<name>王语嫣</name>
  94. ????</employee>
  95. ????<employee>
  96. ????????<empid>e0003</empid>
  97. ????????<name>张无忌</name>
  98. ????</employee>
  99. </employees>
  100. '
  101. create?table?people2?
  102. (?
  103. ????personid?varchar(10)??primary?key?,
  104. ????name?varchar(20)?
  105. ?)
  106. INSERT?people2
  107. SELECT?DISTINCT?b.*?FROM
  108. ????(SELECT?x?=?@doc.query('for?$e?in?//employee??return??//employee[empid?=?$e/empid][last()]'))?a??--FLWOR时,用当前节点去//emploee节点集中找节点集中empid等于当前节点的empid,?在找到的集合中取最后一个利用last()函数
  109. CROSS?APPLY
  110. ????(SELECT?id=t.x.value('empid[1]',name=t.x.value('name[1]','varchar(100)')?FROM?a.x.nodes('//employee')?AS?t(x))?b
  111. SELECT?*?FROM?people2
  112. /*
  113. e0001????萧峰
  114. e0002????段誉
  115. e0003????张无忌
  116. */
  117. GO
  118. drop?table?people2?
  119. GO
  120. --同组一选多,也可应用此方法,不过没有必要,就不再累赘了。
  121. --(3)
  122. --====================================================================
  123. --列名,列值相关
  124. --a,按行聚合
  125. declare?@t?table(Sname?nvarchar(5),??V1?float,????V2?float,????V3?float,??????V4?float,????V5?float,??????V6?float)?
  126. insert?@t?select?N'张三',????0.11?,?0.21?,?0.29,??0.32?,???0.11,????0.08?
  127. insert?@t?select?N'李四',????0.01?,?0.61?,?0.21,??0.73?,???0.21,????0.12?
  128. insert?@t?select?N'张五',????0.31?,?0.23,??0.33?,???0.91,????0.65?
  129. insert?@t?select?N'张六',????0.59?,?0.11,??0.26,??0.13,????0.01,????0.15?
  130. select?b.*?from
  131. ????(select?x=cast((select?*?from?@t?for?xml?path('r'))?as?xml))?a
  132. cross?apply
  133. ????(
  134. ????????select?name=x.query('./Sname/text()'),v=x.query('max(./*[local-name(.)!="Sname"])')?from?a.x.nodes('//r')?as?t(x)??
  135. ????????--r为二级节点(因为文档本身无根节点,即为每项的顶级节点)即为一个r节点表示一条记录.?r下级节点,每个表示一个列,因为列名未知,所以用/*匹配所有节点,因为name为区别列,不参与聚合运算,故用local-name取得来过滤
  136. ????)?b
  137. /*
  138. 张三????0.32
  139. 李四????0.73
  140. 张五????0.91
  141. 张六????0.59
  142. */
  143. --b?,由值引到取列
  144. if?not?object_id('T1')?is?null
  145. ????drop?table?T1
  146. GO
  147. Create?table?T1([tId]?int,[tName]?nvarchar(4))
  148. Insert?T1
  149. select?1,N'zhao'?union?all
  150. select?2,N'qian'?union?all
  151. select?3,N'sun'
  152. Go
  153. -->?-->?借且(Roy)生成測試數據
  154. ?
  155. if?not?object_id('T2')?is?null
  156. ????drop?table?T2
  157. Go
  158. Create?table?T2([tId]?int,[zhao]?nvarchar(1),[qian]?nvarchar(1),[sun]?nvarchar(1))
  159. Insert?T2
  160. select?1,N'a',N'b',N'c'?union?all
  161. select?2,N'd',N'e',N'f'?union?all
  162. select?3,N'g',N'h',N'i'
  163. Go
  164. SELECT?c.tid,c.tName,v?FROM?t1?c
  165. CROSS?APPLY
  166. ????(SELECT?x=(SELECT?*?FROM?t2?WHERE?tid=c.tid?FOR?XML?PATH('r'),TYPE))?a
  167. CROSS?APPLY
  168. ????(SELECT?v=t.x.query('./*[local-name(.)=xs:string(sql:column("c.tName"))?]/text()')?
  169. ????????FROM?a.x.nodes('//r')?AS?t(x)
  170. ????)?b
  171. /*
  172. 1????zhao????a
  173. 2????qian????e
  174. 3????sun????i
  175. */
  176. --c,?列名,列值,与系统表?
  177. CREATE?TABLE?tb(f1?INT,f2?INT,x?INT,z?INT,d?INT,ex?INT,dd?INT,vv?INT)?
  178. INSERT?tb?SELECT?1,2,3,5,11,2423,33?
  179. GO?
  180. SELECT?*?FROM?tb?
  181. GO?
  182. SELECT?name,v?FROM
  183. ??(?SELECT?name?FROM?sys.columns?WHERE?object_idobject_id=object_id('tb','u')?)?a?
  184. CROSS?JOIN
  185. ??(SELECT?x=(SELECT?*?FROM?tb?FOR?XML?PATH('r'),TYPE))?b?
  186. CROSS?APPLY
  187. ?(SELECT?v=t.x.query('./*[local-name(.)=xs:string(sql:column("a.name"))?]/text()')?FROM?b.x.nodes('//r')?AS?t(x)?)?c?
  188. /*
  189. f1??1
  190. f2??2
  191. x???3
  192. z???5
  193. d???11
  194. ex??3
  195. dd??2423
  196. vv??33
  197. */
  198. GO?
  199. DROP?TABLE?tb
  200. GO
  201. --(4)
  202. --一些综合计算
  203. --以下表?ta.a值?yyyymmdd-yyyymmdd表连续时间段,","表单个日期
  204. If?object_id('ta','u')?is?not?null?
  205. ????Drop?table?ta
  206. Go
  207. Create?table?ta(a?varchar(100))
  208. Go
  209. Insert?into?ta
  210. select?'1?|?|20080101-20080911'?
  211. union?all
  212. select?'2?|?|20080101,20080201,20080301,20080515,20080808'
  213. union?all
  214. select?'3?|?|20080101,20080201,20080301,20080515,20081108'
  215. Go
  216. declare?@s?varchar(8)
  217. select?@s=?convert(varchar(8),getdate(),112)
  218. select?stuff(replace(replace(cast(x?as?varchar(1000)),'</item><item>',case?when?type='1'?then?'-'?else?','?end),'</item>',''),6,type?+?'?|?|')?a
  219. ????from
  220. ????(
  221. ????????select?left(a,1)?type,?
  222. ????????????cast(
  223. ????????????????????'<item>'?
  224. ????????????????????+?
  225. ????????????????????replace(
  226. ????????????????????????stuff(a,
  227. ????????????????????????case?when?left(a,1)=1?then?'-'?else?','?end,
  228. ????????????????????????'</item><item>'
  229. ????????????????????????)
  230. ????????????????????+?
  231. ????????????????????'</item>'
  232. ????????????????AS?XML
  233. ????????????????)?x
  234. ????????from?ta
  235. ????)?base
  236. ????where?x.value('
  237. ????????????if?(sql:column("base.type")="1")?then
  238. ????????????????if(
  239. ????????????????????(/item/text())[1]<sql:variable("@s")
  240. ????????????????????and
  241. ????????????????????(/item/text())[2]>sql:variable("@s")
  242. ????????????????)
  243. ????????????????then?1
  244. ????????????????else?0
  245. ????????????else
  246. ????????????????count(//item[text()>sql:variable("@s")])
  247. ????????????'
  248. ????????????,
  249. ????????????'int'
  250. ????????????)>0
  251. go
待续..

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读