简体   繁体   中英

Creating an HTML table string in SQL from a result with gap values

I'm using a mailing template engine that can't accept anything other than SQL output (due to this already being a subquery), so I'm trying to output an HTML table directly as a string.

I need to create a SQL script that through some form of black magic creates a table out of a set of shows with the days as columns, and the show times as table cells. For example:

FR      SA      SU      MO      TU      WE      TH      FR
16:00   11:10   11:10           16:00   12:50
        13:40   13:40                   15:10
        16:00   16:00

I've got a query that gets all the required data and its column and row numbers, but no idea how to turn that into a string value that looks like this for each row:

<tr><td>16:00</td><td>11:10</td><td>11:10</td><td></td><td>16:00</td><td>12:50</td><td></td><td></td></tr>

Here's the query (and sample data) I'm using now:

declare @Shows table(id int, start datetime);
insert into @Shows(id, start) values (801, '2013-12-13 16:00');
insert into @Shows(id, start) values (325, '2013-12-14 11:10');
insert into @Shows(id, start) values (662, '2013-12-14 13:40');
insert into @Shows(id, start) values (771, '2013-12-14 16:00');
insert into @Shows(id, start) values (772, '2013-12-15 11:10');
insert into @Shows(id, start) values (441, '2013-12-15 13:40');
insert into @Shows(id, start) values (775, '2013-12-15 16:00');
insert into @Shows(id, start) values (138, '2013-12-17 16:00');
insert into @Shows(id, start) values (238, '2013-12-18 12:50');
insert into @Shows(id, start) values (947, '2013-12-18 15:10');


declare @DayWrapHour int=3;
declare @FromDate datetime='2013-12-13 15:00';
declare @ToDate datetime = dateadd(day, 8, CONVERT(date, @FromDate));
set @ToDate = DATEADD(hour, @DayWrapHour, @ToDate); --8 days from now, at 3 am

select *, ROW_NUMBER() over (partition by columnindex order by columnindex) as rownumber
from (
    select
        s.Id,
        CONVERT(char(5), CONVERT(time, s.start)) as StartTime,
        DATEDIFF(DAY,
            DATEADD(HOUR, @DayWrapHour, CONVERT(datetime, CONVERT(date, @FromDate))), --@FromDate, at 3 am
            s.start
        ) as columnindex
    from @Shows s
    where s.start between @FromDate and @ToDate
)as sub
order by rownumber, sub.columnindex

I thought that was quite clever already, but I'm stumped on how to do a sort of foreach on this without using non-SQL code, and on how to deal with the data gaps if I do.

Output of that query:

Id  StartTime   columnindex rownumber
801 16:00       0           1
325 11:10       1           1
772 11:10       2           1
138 16:00       4           1
238 12:50       5           1
662 13:40       1           2
441 13:40       2           2
947 15:10       5           2
771 16:00       1           3
775 16:00       2           3

Note that the column amount is fixed, but the row amount is not.

You can use something like this to pivot the columns:

select 
    rownumber
,   col0 = max(case when columnindex = 0 then StartTime end)
,   col1 = max(case when columnindex = 1 then StartTime end)
,   col2 = max(case when columnindex = 2 then StartTime end)
from (
   -- your previous query with the rownumber and columnindex
) x
group by rownumber

And then for xml to generate the html, like they do in this answer: Create HTML Table with SQL FOR XML

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM