0

我正在寻找编写我在 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”&gt;
<AppName=”AppDelta”&gt;
<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 写否?

4

3 回答 3

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 来输出是/否,而不是在 Excel 中这样做。无论哪种方式都可以。

但是,您使用的实际 XML 的结构可能会对这些查询产生影响。你能把它的样本块放在这里吗?您使用的是什么版本的 SQL Server?SQL 2000 的 XML 语法与 SQL 2005+ 有点不同,SQL 2000 中没有 XML 数据类型。

要从查询构建电子表格,Ray Camden 有一篇很好的文章。还有cfspreadsheet的 Adob​​e 文档。

于 2013-08-01T15:21:20.660 回答
1

如果只有三个应用程序列,另一种选择是使用 SQL Server 的 xml 函数在 sql.xml 中生成结果。只需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

然后在您的电子表格中,将自定义单元格格式应用于列以显示是/否而不是 0/1。假设您使用的是 CF 的内置电子表格功能,格式为:

         {dataformat='"Yes";"Yes";"No"'}
于 2013-08-01T03:59:22.747 回答
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>
于 2013-07-31T20:00:04.927 回答