我需要在xml节点列内拆分csv数据。 我正在使用SQL Server2012。我想查询而不创建函数。
例如,数据如下
ID : 1
XMLvalue : <BETA>
<SERIAL NAME="ASSESSMENT"> ASSESSMENT=1,ASSESSMENT=2,ASSESSMENT=3</SERIAL>
<SERIAL NAME="PROJECT"> PROJECT=1,PROJECT=2,PROJECT=3</SERIAL>
</BETA>
ID : 2
XMLvalue : <BETA>
<SERIAL NAME="ASSESSMENT"> ASSESSMENT=4,ASSESSMENT=5,ASSESSMENT=6</SERIAL>
<SERIAL NAME="PROJECT"> PROJECT=4,PROJECT=5,PROJECT=6</SERIAL>
</BETA>
ID : 3
XMLvalue : <BETA>
<SERIAL NAME="ASSESSMENT"> ASSESSMENT=7,ASSESSMENT=8,ASSESSMENT=9</SERIAL>
<SERIAL NAME="PROJECT"> PROJECT=7,PROJECT=8,PROJECT=9</SERIAL>
</BETA>
输出应该如下
ID Assessment PROJECT
1 ASSESSMENT=1 PROJECT=1
1 ASSESSMENT=2 PROJECT=2
1 ASSESSMENT=3 PROJECT=3
2 ASSESSMENT=4 PROJECT=4
2 ASSESSMENT=5 PROJECT=5
2 ASSESSMENT=6 PROJECT=6
3 ASSESSMENT=7 PROJECT=7
3 ASSESSMENT=8 PROJECT=8
3 ASSESSMENT=9 PROJECT=9
我想在不创建函数且仅使用查询的情况下实现以上输出。
我无法创建SQL Fiddle,因此在下面粘贴了create和insert语句。
CREATE TABLE Chart
(
StoreID INT PRIMARY KEY,
XMLvalue XML
);
INSERT INTO Chart Values (1,<BETA>
<SERIAL NAME="ASSESSMENT"> ASSESSMENT=1,ASSESSMENT=2,ASSESSMENT=3</SERIAL>
<SERIAL NAME="PROJECT"> PROJECT=1,PROJECT=2,PROJECT=3</SERIAL>
</BETA>)
INSERT INTO Chart Values (2,<BETA>
<SERIAL NAME="ASSESSMENT"> ASSESSMENT=4,ASSESSMENT=5,ASSESSMENT=6</SERIAL>
<SERIAL NAME="PROJECT"> PROJECT=4,PROJECT=5,PROJECT=6</SERIAL>
</BETA>)
INSERT INTO Chart Values (3,<BETA>
<SERIAL NAME="ASSESSMENT"> ASSESSMENT=7,ASSESSMENT=8,ASSESSMENT=9</SERIAL>
<SERIAL NAME="PROJECT"> PROJECT=7,PROJECT=8,PROJECT=9</SERIAL>
</BETA>)
任何帮助,将不胜感激。
谢谢。
Patchai
答案 0 :(得分:0)
解决方案1
CREATE TABLE #Chart( StoreID INT PRIMARY KEY, XMLvalue XML );
INSERT INTO #Chart Values (1,'<BETA> <SERIAL NAME="ASSESSMENT"> ASSESSMENT="1",ASSESSMENT=2,<"ASSESSMENT=3" ></SERIAL><SERIAL NAME="PROJECT"> PROJECT=1,PROJECT=2,PROJECT=3</SERIAL></BETA>')
INSERT INTO #Chart Values (2,'<BETA> <SERIAL NAME="ASSESSMENT"> ASSESSMENT=4,ASSESSMENT=5,ASSESSMENT=6</SERIAL><SERIAL NAME="PROJECT"> PROJECT=4,PROJECT=5,PROJECT=6</SERIAL></BETA>')
INSERT INTO #Chart Values (3,'<BETA> <SERIAL NAME="ASSESSMENT"> ASSESSMENT=7,ASSESSMENT=8,ASSESSMENT=9</SERIAL><SERIAL NAME="PROJECT"> PROJECT=7,PROJECT=8,PROJECT=9</SERIAL></BETA>')
INSERT INTO #Chart Values (4,'<BETA> <SERIAL NAME="ASSESSMENT"> ASSESSMENT=10,ASSESSMENT=11,ASSESSMENT=12,ASSESSMENT=13,ASSESSMENT=14,ASSESSMENT=15</SERIAL><SERIAL NAME="PROJECT"> PROJECT=10,PROJECT=11,PROJECT=12,PROJECT=13</SERIAL></BETA>')
SELECT SToreID,
MAX(CASE WHEN Name = 'ASSESSMENT' THEN LTRIM(RTRIM(Value)) END) AS ASSESSMENT,
MAX(CASE WHEN Name = 'PROJECT' THEN LTRIM(RTRIM(Value)) END) AS PROJECT
FROM
(
SELECT StoreID,u.value('../@NAME','varchar(100)') AS Name,u.query('.').value('.','varchar(max)') AS Value,
ROW_NUMBER() OVER (PARTITION BY SToreID,u.value('../@NAME','varchar(100)') ORDER BY u.query('.').value('.','varchar(max)') ) AS Seq
FROM (
SELECT StoreID,CAST(REPLACE(REPLACE(REPLACE(CAST(XMLValue AS varchar(max)),',','</Value><Value>'),'</SERIAL>','</Value></SERIAL>'),'">','"><Value>')AS xml) AS XMLValue
FROM #Chart
) c
CROSS APPLY XMLValue.nodes('/BETA/SERIAL/Value')t(u)
)m
GROUP BY StoreID,Seq
ORDER BY SToreID,Seq
DROP TABLE #Chart
解决方案2
CREATE TABLE #Chart( StoreID INT PRIMARY KEY, XMLvalue XML );
INSERT INTO #Chart Values (1,'<BETA> <SERIAL NAME="ASSESSMENT"> ASSESSMENT=0,</Value><Value>="1",ASSESSMENT=2,<"ASSESSMENT=3" ></SERIAL><SERIAL NAME="PROJECT"> PROJECT=1,PROJECT=2,PROJECT=3</SERIAL></BETA>')
INSERT INTO #Chart Values (2,'<BETA> <SERIAL NAME="ASSESSMENT"> ASSESSMENT=4,ASSESSMENT=65,ASSESSMENT=16</SERIAL><SERIAL NAME="PROJECT"> PROJECT=4,PROJECT=5,PROJECT=6</SERIAL></BETA>')
INSERT INTO #Chart Values (3,'<BETA> <SERIAL NAME="ASSESSMENT"> ASSESSMENT=7,ASSESSMENT=8,ASSESSMENT=9</SERIAL><SERIAL NAME="PROJECT"> PROJECT=7,PROJECT=8,PROJECT=9</SERIAL></BETA>')
INSERT INTO #Chart Values (4,'<BETA> <SERIAL NAME="ASSESSMENT"> ASSESSMENT=10,ASSESSMENT=11,ASSESSMENT=12,ASSESSMENT=13,ASSESSMENT=14,ASSESSMENT=15</SERIAL><SERIAL NAME="PROJECT"> PROJECT=10,PROJECT=11,PROJECT=12,PROJECT=13</SERIAL></BETA>')
go
SELECT * FROM #Chart
go
WITH lists AS (
SELECT StoreID,
assessments = ltrim(A.a.value('(./text())[1]', 'nvarchar(MAX)') COLLATE Latin1_General_BIN),
projects = ltrim(P.p.value('(./text())[1]', 'nvarchar(MAX)') COLLATE Latin1_General_BIN)
FROM #Chart
CROSS APPLY XMLvalue.nodes('/BETA/SERIAL[@NAME="ASSESSMENT"]') AS A(a)
CROSS APPLY XMLvalue.nodes('/BETA/SERIAL[@NAME="PROJECT"]') AS P(p)
), assess_unwind AS (
SELECT StoreID, assessments, listpos = 1,
start = convert(bigint, 1),
stop = charindex(',', assessments + ',')
FROM lists
UNION ALL
SELECT StoreID, assessments, listpos + 1, start = stop + 1,
stop = charindex(',', assessments + ',', stop + 1)
FROM assess_unwind
WHERE stop > 0
), proj_unwind AS (
SELECT StoreID, projects, listpos = 1,
start = convert(bigint, 1),
stop = charindex(',', projects + ',')
FROM lists
UNION ALL
SELECT StoreID, projects, listpos + 1, start = stop + 1,
stop = charindex(',', projects + ',', stop + 1)
FROM proj_unwind
WHERE stop > 0
)
SELECT a.StoreID,
substring(a.assessments, a.start, CASE WHEN a.stop > 0 THEN a.stop - a.start ELSE 0 END),
substring(p.projects, p.start, CASE WHEN p.stop > 0 THEN p.stop - p.start ELSE 0 END)
FROM assess_unwind a
JOIN proj_unwind p ON a.StoreID = p.StoreID
AND a.listpos = p.listpos
WHERE a.stop > 0
AND p.stop > 0
ORDER BY a.StoreID, a.listpos
OPTION (MAXRECURSION 0)
go
DROP TABLE #Chart