我有一个数据集,看起来是这样的:
Gender | Age | Name
Male | 30 | Bill
Female | 27 | Jenny
Female | 27 | Debby
Male | 44 | Frank
我试图显示此为特殊格式的HTML代码:
<ul>
<li>Male
<ul>
<li>30
<ul>
<li>Bill</li>
</ul>
</li>
<li>44
<ul>
<li>Frank</li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li>Female
<ul>
<li>27
<ul>
<li>Jenny</li>
<li>Debby</li>
</ul>
</li>
</ul>
</li>
</ul>
我尝试使用FOR XML
但并没有给我一直在寻找的结果。 它没有删除多个Gender
和Age
字段返回。 正如你在这个HTML看到它是以复利这一切,只在最后节点给予重复。
阿龙贝特朗提供了这里的好方法返回SELECT语句格式的HTML ,似乎在2008年SQL完美地工作,但我一直在寻找的东西,在2005年的工作为好,除了这个小东西,就像+=
运营商并设置默认DECLARE值,只是没有在2005年显示。
怎么会这样的事情在SQL Server 2005可以实现吗?
declare @T table
(
Gender varchar(10),
Age int,
Name varchar(10)
)
insert into @T values ('Male', 30, 'Bill')
insert into @T values ('Female', 27, 'Jenny')
insert into @T values ('Female', 27, 'Debby')
insert into @T values ('Male', 44, 'Frank')
select Gender as 'li',
(select T2.Age as 'li',
(select T3.Name as 'li'
from @T as T3
where T2.Age = T3.Age and
T1.Gender = T3.Gender
for xml path(''), root('ul'), type) as 'li'
from @T as T2
where T1.Gender = T2.Gender
group by T2.Age
for xml path(''), root('ul'), type) as 'li'
from @T as T1
group by Gender
for xml path('ul')
下面是SQL Server 2005中,它只需轻微的调整代码从我昨天给出了答案 ,其被要求用于SQL Server 2008中具体如下:
DECLARE @x TABLE(Gender VARCHAR(6), Age INT, Name VARCHAR(32));
INSERT @x SELECT 'Male', 30, 'Bill' UNION ALL SELECT 'Female', 27, 'Jenny'
UNION ALL SELECT 'Female', 27, 'Debby' UNION ALL SELECT 'Male', 44, 'Frank';
DECLARE @html NVARCHAR(MAX);
SET @html = N'';
;WITH x AS ( SELECT x.Age, x.Gender, x.Name,
dr = DENSE_RANK() OVER (PARTITION BY x.Gender ORDER BY x.Age),
gn = ROW_NUMBER() OVER (PARTITION BY x.Gender ORDER BY x.Age),
rn = ROW_NUMBER() OVER (ORDER BY x.Gender DESC, x.Age)
FROM @x AS x ) SELECT @html = @html +
CHAR(13) + CHAR(10) + CASE WHEN c1.gn = 1 THEN
CASE WHEN c1.rn > 1 THEN '</li></ul></li></ul>' ELSE '' END + '<ul><li>'
+ c1.Gender ELSE '' END + CHAR(13) + CHAR(10) + CHAR(9)
+ CASE WHEN c1.gn = 1 OR c1.Age <> c3.Age THEN
CASE WHEN c1.gn > 1 THEN '</li>' ELSE '<ul>' END + '<li>'
+ CONVERT(VARCHAR(32), c1.Age) ELSE '' END + CHAR(13) + CHAR(10) + CHAR(9)
+ CHAR(9) + CASE WHEN (c1.gn = 1 OR c1.Age <> c3.Age) THEN '<ul>' ELSE '' END
+ '<li>' + c1.Name + '</li>' + CASE WHEN c1.Age <> c2.Age OR c1.dr <> c2.dr
THEN '</ul>' ELSE '' END
FROM x AS c1
LEFT OUTER JOIN x AS c2
ON c1.rn = c2.rn - 1
LEFT OUTER JOIN x AS c3
ON c1.rn = c3.rn + 1
ORDER BY c1.Gender DESC, c1.Age;
SELECT @html = @html + '</ul></li></ul></li></ul>';
PRINT @html; -- note you will need to deal with this
-- in another way if the string is large
这里是证明了它的工作原理:
SET ANSI_WARNINGS ON;
DECLARE @Test TABLE
(
Gender VARCHAR(10) NOT NULL,
Age INT NOT NULL,
Name VARCHAR(50) NOT NULL
);
INSERT @Test (Gender, Age, Name)
SELECT 'Male' ,30 ,'Bill'
UNION ALL
SELECT 'Female',27 ,'Jenny'
UNION ALL
SELECT 'Female',27 ,'Debby'
UNION ALL
SELECT 'Male' ,44 ,'Frank';
DECLARE @x XML;
SET @x =
(
SELECT *
FROM @Test t
FOR XML RAW, ROOT
);
SELECT @x AS [Source];
SELECT @x.query('
for $g in distinct-values(//root/row/@Gender) (: or for $g in ("Male", "Female") :)
return
<ul>
<li>
{data($g)}
<ul>
{
for $a in distinct-values(//root/row[@Gender=$g]/@Age)
return <li>{data($a)}
<ul>
{
for $n in //root/row
where $n/@Gender=$g and $n/@Age = $a
return <li>{data($n/@Name)}</li>
}</ul></li>
}
</ul>
</li>
</ul>
') AS Result;
Refences: SQL服务器的XQuery