我希望看到我在ColdFusion 10中编写此报告的最佳方式是什么。
基本上,它包括从MSSQL数据库中的两个表读取数据,根据它在特定列上找到的内容应用某些条件,将数据填充到excel中并通过电子邮件发送出去。我之前写的报告就像从表中读取数据一样简单,使用POIUTILITY创建电子表格并通过电子邮件发送,但由于条件的原因,这个报告有点不同。我已经读过使用cfspreadsheet而不是poiutility,但在这种情况下我不太确定。
以下是表格布局的示例,就像我可以轻松一样:
Table1
ID | Name | Address
Table2
ID | AppsInfo
在excel报告中,我将有一张表格,其中的数据布局类似于以下内容:
ID | Name | Address | AppAlpha | AppBravo | AppDelta |
12345 | John | 123 Ave | Yes | Yes | No |
我的问题是,table2上的AppsInfo列包含每个ID的xml格式:
<start>
<id=”12345”>
<AppName=”AppDelta”>
<AppName=”AppBravo”
</id>
</start>
在我的Excel工作表的每一行中,数据都会写出来,如果特定ID的appsinfo列包含一个应用程序,那么在相应的行上将其列为是,如果它不包含该应用程序,则为
从上面的布局示例开始,excel的最终格式将以这种方式显示:
ID | Name | Address | AppAlpha | AppBravo | AppDelta |
12345 | John | 123 Ave | No | Yes | Yes |
等等每个ID ...
开发它的最佳方法是什么,如果它包含table2 appsinfo列上的特定应用程序,它会将其写为是,如果没有,则为相应行上的每个ID写入no?
答案 0 :(得分:2)
Leigh打败了我的答案,但我有一个使用SQL的XML功能的类似解决方案。使用XML可能很麻烦,但SQL Server具有使用XML的语法。
SELECT t1.ID
, t1.Name
, t1.Address
--, t2.AppsInfo
, CASE WHEN t2.AppsInfo.exist('//start/id/AppName[@value="AppAlpha"]') = 1 THEN 'Yes' ELSE 'No' END AS AppAlpha
, CASE WHEN t2.AppsInfo.exist('//start/id/AppName[@value="AppBravo"]') = 1 THEN 'Yes' ELSE 'No' END AS AppBravo
, CASE WHEN t2.AppsInfo.exist('//start/id/AppName[@value="AppDelta"]') = 1 THEN 'Yes' ELSE 'No' END AS AppDelta
FROM #table1 t1
INNER JOIN #table2 t2 ON t1.ID = t2.ID
我的设置是:
Create TABLE #table1 ( ID int, Name varchar(100), Address varchar(200) )
Create TABLE #table2 ( ID int, AppsInfo xml )
INSERT INTO #table1 (ID, Name, Address)
SELECT 1, 'John', '123 Sesame St'
UNION ALL
SELECT 2, 'Jim', '42 Douglas Ln'
UNION ALL
SELECT 3, 'Jack', '1 Elm St'
UNION ALL
SELECT 4, 'Joe', '21 Jump St'
INSERT INTO #table2 (ID, AppsInfo)
SELECT 1, '<start><id value="1"><AppName value="AppDelta"/><AppName value="AppBravo"/></id></start>'
UNION ALL
SELECT 2, '<start><id value="2"><AppName value="AppAlpha"/><AppName value="AppDelta"/><AppName value="AppBravo"/></id></start>'
UNION ALL
SELECT 3, '<start><id value="3"><AppName value="AppBravo"/></id></start>'
UNION ALL
SELECT 4, '<start><id value="4"><AppName/></id></start>'
我还必须稍微修改XML以使其有效。我的解决方案和Leigh之间唯一真正的区别是我使用SQL CASE输出Yes / No而不是在Excel中输出。无论哪种方式都可行。
但是,您使用的实际XML的结构可能会对这些查询产生影响。你能把它的样本块放在这里吗?您使用的是哪个版本的SQL Server? SQL 2000的XML语法与SQL 2005+略有不同,SQL 2000中没有XML数据类型。
从查询Ray Camden has a good article构建电子表格。还有cfspreadsheet的Adobe文档。
答案 1 :(得分:1)
如果只有三个应用程序列,则另一个选项是使用SQL Server的xml函数在sql中生成结果。只需为三列中的每一列返回bit
值即可。 (注意:我调整了帖子中的xml示例以使其有效,但SQLFiddle显示了一般的想法。)
SELECT t1.ID
, t1.Name
, t1.Address
, t2.appsInfo.exist('//start/id/App[@Name="AppAlpha"]') AS AppAlpha
, t2.appsInfo.exist('//start/id/App[@Name="AppBravo"]') AS AppBravo
, t2.appsInfo.exist('//start/id/App[@Name="AppDelta"]') AS AppDelta
FROM @table1 t1 INNER JOIN @table2 t2 ON t2.ID = t1.ID
然后在电子表格中,将custom cell format应用于列以显示是/否而不是0/1。假设您使用的是CF的内置电子表格功能,格式为:
{dataformat='"Yes";"Yes";"No"'}
答案 2 :(得分:0)
我认为最容易和最脏的方法是通过字符串检测。
<cfquery name="AppData" datasource="MyDSN">
SELECT
t1.id, t1.name, t1.address, t2.appinfo
FROM
table1 t1
INNER JOIN table2 t2 ON t1.id = t2.id
</cfquery>
<cfscript>
// Return a Yes/No for App's Existence in a string
function checkApp( app, string) {
return findNoCase( app, string ) ? 'NO' : 'YES';
}
</cfscript>
<cfoutput query="AppData">
#id# #name# #address# #checkApp( 'AppDelta', appinfo )# #checkApp( 'AppBravo', appinfo )#
</cfoutput>