惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Security Blog
Microsoft Security Blog
S
Secure Thoughts
酷 壳 – CoolShell
酷 壳 – CoolShell
S
SegmentFault 最新的问题
WordPress大学
WordPress大学
Hugging Face - Blog
Hugging Face - Blog
人人都是产品经理
人人都是产品经理
美团技术团队
博客园 - 三生石上(FineUI控件)
Jina AI
Jina AI
V
Visual Studio Blog
腾讯CDC
小众软件
小众软件
有赞技术团队
有赞技术团队
博客园 - 聂微东
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
IT之家
IT之家
C
CERT Recently Published Vulnerability Notes
大猫的无限游戏
大猫的无限游戏
T
Threat Research - Cisco Blogs
SecWiki News
SecWiki News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
宝玉的分享
宝玉的分享
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The Hacker News
The Hacker News
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
Troy Hunt's Blog
月光博客
月光博客
雷峰网
雷峰网
T
Tor Project blog
I
Intezer
S
Securelist
罗磊的独立博客
The Register - Security
The Register - Security
H
Hackread – Cybersecurity News, Data Breaches, AI and More
NISL@THU
NISL@THU
Google Online Security Blog
Google Online Security Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Cisco Talos Blog
Cisco Talos Blog
云风的 BLOG
云风的 BLOG
www.infosecurity-magazine.com
www.infosecurity-magazine.com
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
L
Lohrmann on Cybersecurity
The Cloudflare Blog
Attack and Defense Labs
Attack and Defense Labs
P
Privacy International News Feed
W
WeLiveSecurity
Forbes - Security
Forbes - Security
量子位
Last Week in AI
Last Week in AI

博客园 - 钢钢

Hadoop 调研笔记 使用SerialPort 对象实现串口拨号器通信[下] 使用SerialPort 对象实现串口拨号器通信[上] SQL Server 2005 创建分区表 考勤表生成工具介绍及使用说明 Modbus RTU 通信工具设计 SQL Server 中,实现 varbinary 与 varchar 类型之间的数据转换 使用C# 实现串口拨号器的SIM卡通信[修正版] 使用C# 实现串口拨号器的SIM卡通信 什么是BCD 码 我的INI 配置文件读写动态库 关于ASP.NET 将数据导出成Excel 的总结[补充] 子角色权限的实现 两个横向菜单栏示例 C# 实现16进制和字符串之间转换的代码[转] 固定GridView 的表头和某几列 SQL Server 中几个有用的特殊函数 关于ASP.NET 将数据导出成Excel 的总结[下] 关于ASP.NET 将数据导出成Excel 的总结[中]
SQLServer 2005 XML 在 T-SQL 查询中的典型应用[转]
钢钢 · 2011-10-18 · via 博客园 - 钢钢

--(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
*/

--(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