Return Select Statement as formatted HTML (SQL 2005)

这一生的挚爱 提交于 2019-12-23 06:39:07

问题


I have a data set that looks something like this:

   Gender | Age | Name
    Male  | 30  | Bill
  Female  | 27  | Jenny
  Female  | 27  | Debby 
   Male   | 44  | Frank

And I'm trying to display this as specially formatted HTML code:

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

I tried using FOR XML but that didn't give the results I was looking for. It didn't remove the multiple Gender and Age fields returned. As you can see in this HTML it is compounding it all and only giving duplicates at the end node.

Aaron Bertrand provided an excellent method here Return Select Statement as formatted HTML that seems to work perfectly in SQL 2008, but I was looking for something that worked in 2005 as well, besides the little stuff, like += operators and setting default DECLARE values, just doesn't display in 2005.

How would something like this be achieved in SQL Server 2005?


回答1:


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')



回答2:


Here is the code for SQL Server 2005, which only required minor adjustments from the answer I gave yesterday which was requested for SQL Server 2008 specifically:

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

And here is proof that it works:




回答3:


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 Server XQuery



来源:https://stackoverflow.com/questions/10300764/return-select-statement-as-formatted-html-sql-2005

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!