当前位置: 首页 > news >正文

拆解组装SQL字符串全过程

先看下面这段代码, 它将sql字符串先分割为行集,做一定处理后再合并为单行:

use tempdb
go

if ( object_id ( 't_Item' ) is not null ) drop table t_item
go
if ( object_id ( 't_Buy' ) is not null ) drop table t_Buy
go
create table t_Item ( Item_ID int , Item_Name varchar ( 10 ))
insert into t_Item select 1 , '面包' union select 2 , '衣服' union select 3 , '鞋子'
create table t_Buy ( Person varchar ( 10 ), WantBuy varchar ( 10 ))
insert into t_Buy select '小张' , '1,2' union select '小王' , '1,2,3'

go
/*原始表数据
Person WantBuy
---------- ----------
小张 1,2
小王 1,2,3
*/

/*要求查询结果
Person WantBuy
---------- -----------------
小王 面包,衣服,鞋子
小张 面包,衣服
*/

select Person , WantBuy = cast ( replace ( WantBuy , '</v><v>' , ',' ) as xml ). value ( '.' , 'varchar(max)' )
from ( select distinct Person from t_Buy ) ta outer apply (
select WantBuy = ( select WantBuy as v from
(
select Person , c . Item_Name as WantBuy from (
select Person , convert ( xml , '<v>' + replace ( WantBuy , ',' , '</v><v>' ) + '</v>' ) as WantBuy
from t_Buy ) a outer apply
(
select t . c . value ( '.' , 'varchar(max)' ) AS WantBuy from a . WantBuy . nodes ( '//v' ) AS t ( c )
)b inner join t_Item c on b . wantbuy = c . item_id
) d where person = ta . person for xml path ( '' ))
) tb

如果这段代码对于你来说是小case 那你就可以忽略此文,去论坛灌水去了。如果你还不了解他的工作原理,请继续耐心看完下面的分解过程。你需要单独理解以下内容:

SQL CTE(Common Table Expressions:公共表达式)

http://msdn.microsoft.com/zh-cn/library/ms190766.aspx

apply 关键字的用法

http://msdn.microsoft.com/zh-cn/library/ms175156.aspx

XQuery查询

http://blog.csdn.net/jinjazz/archive/2009/08/13/4443585.aspx

For XML子句

http://msdn.microsoft.com/zh-cn/library/ms190922.aspx

下面把上述语句分解为五个步骤,最后一个步骤就是最后需要的结果。

use tempdb
go

if ( object_id ( 't_Item' ) is not null ) drop table t_item
go
if ( object_id ( 't_Buy' ) is not null ) drop table t_Buy
go
create table t_Item ( Item_ID int , Item_Name varchar ( 10 ))
insert into t_Item select 1 , '面包' union select 2 , '衣服' union select 3 , '鞋子'
create table t_Buy ( Person varchar ( 10 ), WantBuy varchar ( 10 ))
insert into t_Buy select '小张' , '1,2' union select '小王' , '1,2,3'

go

/*第一步把WantBuy转为xml
Person WantBuy
---------- ----------------------------
小张 <v>1</v><v>2</v>
小王 <v>1</v><v>2</v><v>3</v>
*/

; with t1 as
(
select Person , convert ( xml , '<v>' + replace ( a . WantBuy , ',' , '</v><v>' ) + '</v>' ) as WantBuy
from t_Buy a
)


/*第二步把WantBuy字段拆分为多行
Person WantBuy
---------- --------
小张 1
小张 2
小王 1
小王 2
小王 3
*/
, t2 as
(
select a . Person , b . WantBuy from t1 a outer apply
(
select t . c . value ( '.' , 'varchar(max)' ) AS WantBuy from a . WantBuy . nodes ( '//v' ) AS t ( c )
)b
)
/*第三步把WantBuy字段转为物品的名称
person item_name
---------- ----------
小张 面包
小张 衣服
小王 面包
小王 衣服
小王 鞋子
*/
, t3 as
(
select a . person , b . item_name from t2 a inner join t_Item b on a . wantbuy = b . item_id
)
/*第四步把WantBuy字段按照人名来聚合
Person WantBuy
---------- ------------------------------------
小王 <v>面包</v><v>衣服</v><v>鞋子</v>
小张 <v>面包</v><v>衣服</v>
*/
, t4 as
(
select * from ( select distinct Person from t_Buy ) a outer apply
(
select WantBuy = ( select Item_Name as v from t3 where person = a . person for xml path ( '' ))
)b
)

/*第五步把XML字段转为逗号分割的普通字段
Person WantBuy
---------- -----------------
小王 面包,衣服,鞋子
小张 面包,衣服
*/
, t5 as
(
select Person , WantBuy = cast ( replace ( WantBuy , '</v><v>' , ',' ) as xml ). value ( '.' , 'varchar(max)' ) from t4
)
select * from t5

我们这里不得不夸奖一下SQLServer2005的CTE表达式,它可以把很复杂的嵌套查询分解为简单的多步查询。

相关文章:

  • ROS局部规划器中的轨迹模拟策略-DWA使用与否的差别
  • 商业智能在中国企业的成熟应用,还需要以业务为核心。
  • 【全局路径规划】人工势场 Artificial Potential Field
  • 用Linux替代Windows
  • 【全局路径规划】A*算法 A* Search Algorithm
  • 【局部路径规划】DWA动态窗口法 Dynamic Window Approach
  • 【运动规划】人工势场构造扩展多点人工势场组合控制高自由度机器人
  • 【运动规划】BFP搜索Best-First Planner及填充势场Local minima
  • 【运动规划】RRT快速搜索随机树 Rapidly Exploring Random Tree
  • 【路径规划】PRM 概率道路图法 Probabilistic Roadmap Method
  • ArcGIS Server Java ADF 案例教程 39
  • 【轨迹生成】参数化最优控制 约束-控制-图形参数
  • 【路径规划】状态格算法 State Lattices Algorithm
  • ArcGIS Server Java ADF 案例教程 40
  • 路径规划论文阅读小记
  • (十五)java多线程之并发集合ArrayBlockingQueue
  • [deviceone开发]-do_Webview的基本示例
  • 【跃迁之路】【733天】程序员高效学习方法论探索系列(实验阶段490-2019.2.23)...
  • 03Go 类型总结
  • 2017前端实习生面试总结
  • Android优雅地处理按钮重复点击
  • canvas绘制圆角头像
  • extjs4学习之配置
  • JavaScript创建对象的四种方式
  • Javascript基础之Array数组API
  • JavaScript新鲜事·第5期
  • java架构面试锦集:开源框架+并发+数据结构+大企必备面试题
  • js如何打印object对象
  • Redis学习笔记 - pipline(流水线、管道)
  • SpiderData 2019年2月16日 DApp数据排行榜
  • Spring Cloud Feign的两种使用姿势
  • Sublime text 3 3103 注册码
  • Travix是如何部署应用程序到Kubernetes上的
  • 计算机在识别图像时“看到”了什么?
  • 如何优雅的使用vue+Dcloud(Hbuild)开发混合app
  • 项目实战-Api的解决方案
  • 智能合约开发环境搭建及Hello World合约
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • 数据可视化之下发图实践
  • 组复制官方翻译九、Group Replication Technical Details
  • (14)学习笔记:动手深度学习(Pytorch神经网络基础)
  • (3)选择元素——(17)练习(Exercises)
  • (HAL库版)freeRTOS移植STMF103
  • (Redis使用系列) Springboot 实现Redis 同数据源动态切换db 八
  • (Redis使用系列) SpringBoot中Redis的RedisConfig 二
  • (附源码)springboot掌上博客系统 毕业设计063131
  • (附源码)ssm失物招领系统 毕业设计 182317
  • (九)One-Wire总线-DS18B20
  • (九十四)函数和二维数组
  • (数据大屏)(Hadoop)基于SSM框架的学院校友管理系统的设计与实现+文档
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • (轉貼) UML中文FAQ (OO) (UML)
  • .NET MAUI学习笔记——2.构建第一个程序_初级篇
  • .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验
  • @EnableConfigurationProperties注解使用