--(1)
--====================================================================
--拆分
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
*/
;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
*/
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
--同组一选多,也可应用此方法,不过没有必要,就不再累赘了。
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
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
没有数据我很难帮你调,你看看这个例子:
SELECT Customer.custid AS [@custid],
Customer.companyname AS [companyname]
FROM Sales.Customers AS Customer
WHERE Customer.custid <= 2
ORDER BY Customer.custid
FOR XML PATH ('Customer'), ROOT('Customers');
insert into yshm
select 1,'a1','b1','c1' union all
select 2,'a2','b2','c2' union all
select 3,'a3','b3','c3'
insert into yshd
select 1,'d1','e1','f1' union all -- 1
select 1,'d2','e2','f2' union all
select 2,'d3','e3','f3' union all -- 2
select 3,'d4','e4','f4' union all -- 3
select 3,'d5','e5','f5'
declare ap scroll cursor for select mid,a,b,c from yshm
open ap
fetch first from ap into @mid,@a,@b,@c
while(@@fetch_status<>-1)
begin
select @xmldata=@xmldata
+'<Bill mid="'+rtrim(@mid)+'" cola="'+@a+'" colb="'+@b+'" colc="'+@c+'" >'
+'<DataField>',
@x=''
select @x=@x+'<Data cold="'+d+'" e="'+e+'" f="'+f+'" />'
from yshd where mid=@mid
insert into yshm
select 1,'a1','b1','c1' union all
select 2,'a2','b2','c2' union all
select 3,'a3','b3','c3'
insert into yshd
select 1,'d1','e1','f1' union all -- 1
select 1,'d2','e2','f2' union all
select 2,'d3','e3','f3' union all -- 2
select 3,'d4','e4','f4' union all -- 3
select 3,'d5','e5','f5'
declare ap cursor static for select mid,a,b,c from yshm
open ap
fetch first from ap into @mid,@a,@b,@c
while(@@fetch_status<>-1)
begin
select @xmldata=@xmldata
+'<Bill mid="'+rtrim(@mid)+'" cola="'+@a+'" colb="'+@b+'" colc="'+@c+'" >'
+'<DataField>',
@x=''
select @x=@x+'<Data cold="'+d+'" e="'+e+'" f="'+f+'" />'
from yshd where mid=@mid
select @xmldata=@xmldata+@x+'</DataField></Bill>'
fetch next from ap into @mid,@a,@b,@c
end
close ap
deallocate ap
select @xmldata=@xmldata+'</Event></Document>'
truncate table xmltable
insert into xmltable(xmldata) values(@xmldata)
exec master..xp_cmdshell 'bcp "select cast(xmldata as xml) from DBAP.dbo.xmltable" queryout D:\yangsh.xml -S "." -U "sa" -P "001332@qq" -c -w '
select @xml = CAST(xx as nvarchar(max))
from
(
select *
from
(
select
FromCorpID ,
ActDate ,
Actor ,
CorpOrderID ,
BillID ,
Name,
cast((select UpperCorpOrderID,Code
from tt t2
where t1.FromCorpID = t2.FromCorpID and
t1.Actor = t2.Actor and
t1.CorpOrderID = t2.CorpOrderID and
t1.BillID = t2.BillID
for xml raw('Data')--,root('')
) as xml) DataField
from tt t1
group by FromCorpID ,
ActDate ,
Actor ,
CorpOrderID ,
BillID ,
Name
)a
for xml raw('Bill'),type
)b(xx)
--(1)
--====================================================================
--拆分
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
*/
;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
*/
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
--同组一选多,也可应用此方法,不过没有必要,就不再累赘了。
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
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
没有数据我很难帮你调,你看看这个例子:
SELECT Customer.custid AS [@custid],
Customer.companyname AS [companyname]
FROM Sales.Customers AS Customer
WHERE Customer.custid <= 2
ORDER BY Customer.custid
FOR XML PATH ('Customer'), ROOT('Customers');
insert into yshm
select 1,'a1','b1','c1' union all
select 2,'a2','b2','c2' union all
select 3,'a3','b3','c3'
insert into yshd
select 1,'d1','e1','f1' union all -- 1
select 1,'d2','e2','f2' union all
select 2,'d3','e3','f3' union all -- 2
select 3,'d4','e4','f4' union all -- 3
select 3,'d5','e5','f5'
declare ap scroll cursor for select mid,a,b,c from yshm
open ap
fetch first from ap into @mid,@a,@b,@c
while(@@fetch_status<>-1)
begin
select @xmldata=@xmldata
+'<Bill mid="'+rtrim(@mid)+'" cola="'+@a+'" colb="'+@b+'" colc="'+@c+'" >'
+'<DataField>',
@x=''
select @x=@x+'<Data cold="'+d+'" e="'+e+'" f="'+f+'" />'
from yshd where mid=@mid
insert into yshm
select 1,'a1','b1','c1' union all
select 2,'a2','b2','c2' union all
select 3,'a3','b3','c3'
insert into yshd
select 1,'d1','e1','f1' union all -- 1
select 1,'d2','e2','f2' union all
select 2,'d3','e3','f3' union all -- 2
select 3,'d4','e4','f4' union all -- 3
select 3,'d5','e5','f5'
declare ap cursor static for select mid,a,b,c from yshm
open ap
fetch first from ap into @mid,@a,@b,@c
while(@@fetch_status<>-1)
begin
select @xmldata=@xmldata
+'<Bill mid="'+rtrim(@mid)+'" cola="'+@a+'" colb="'+@b+'" colc="'+@c+'" >'
+'<DataField>',
@x=''
select @x=@x+'<Data cold="'+d+'" e="'+e+'" f="'+f+'" />'
from yshd where mid=@mid
select @xmldata=@xmldata+@x+'</DataField></Bill>'
fetch next from ap into @mid,@a,@b,@c
end
close ap
deallocate ap
select @xmldata=@xmldata+'</Event></Document>'
truncate table xmltable
insert into xmltable(xmldata) values(@xmldata)
exec master..xp_cmdshell 'bcp "select cast(xmldata as xml) from DBAP.dbo.xmltable" queryout D:\yangsh.xml -S "." -U "sa" -P "001332@qq" -c -w '
select @xml = CAST(xx as nvarchar(max))
from
(
select *
from
(
select
FromCorpID ,
ActDate ,
Actor ,
CorpOrderID ,
BillID ,
Name,
cast((select UpperCorpOrderID,Code
from tt t2
where t1.FromCorpID = t2.FromCorpID and
t1.Actor = t2.Actor and
t1.CorpOrderID = t2.CorpOrderID and
t1.BillID = t2.BillID
for xml raw('Data')--,root('')
) as xml) DataField
from tt t1
group by FromCorpID ,
ActDate ,
Actor ,
CorpOrderID ,
BillID ,
Name
)a
for xml raw('Bill'),type
)b(xx)