【问题标题】:CF query issue involving users and locations涉及用户和位置的 CF 查询问题
【发布时间】:2016-04-06 20:46:44
【问题描述】:

我正在尝试找出正确设置查询的最佳方法。基本上我有一个迷你表格询问locationEmployeeNameStartDateEndDate。不幸的是,我在两个无法链接的不同服务器上使用了两个 MS SQL Server 表。

我的目标是有 5 列
Associate Name |地点名称 |位置关联清单 |总位置清单 |关联百分比

我使用的主表是 cl_checklists:我使用的三列是 date,用于检查表单上所选日期之间的日期,associate 用于 EmployeeNames,trans_location 用于不同位置。

    <cfset result = {} /> 
<cftry> 
    <cfset date1 = CREATEODBCDATETIME(form.StartDate & '00:00:00')>
    <cfset date2 = CREATEODBCDATETIME(form.EndDate & '23:59:59')>

    <cfquery datasource="#application.dsn#" name="GetEmployeeInfo">
        SELECT  *
        FROM    cl_checklists
        WHERE   date >=  <cfqueryparam value="#date1#" cfsqltype="cf_sql_timestamp" />
                AND date <= <cfqueryparam value="#date2#" cfsqltype="cf_sql_timestamp" />
                AND trans_location IN ( <cfqueryparam value="#FORM.location#" cfsqltype="cf_sql_varchar" list="true" />  )
                AND associate IN ( <cfqueryparam value="028,998,28" cfsqltype="cf_sql_varchar" list="true" />  )
    </cfquery>

     <cffunction name="getop_id" access="public" returntype="string"> 
        <cfargument name="associate"  > 
        <cfquery name="spitOutop_id" datasource="#application.userinfo_dsn#"> 
            SELECT assoc_name 
            FROM dbo.tco_associates 
            WHERE assoc_id= #arguments.associate# 
        </cfquery> 
        <cfreturn spitOutop_id.assoc_name > 
     </cffunction> 

<table border="1" id="Checklist_Stats">
    <thead>
        <th><strong>Associate Name</strong></th>
        <th><strong>Location</strong></th>
        <th><strong>Checklists Generated by Associate</strong></th>
        <th><strong>Checklists Generated by Selected Location(s)</strong></th>
        <th><strong>Associate Percentage of Location Total</strong></th>   
    </thead>
    <tbody>
    <cfquery name="allAssociatesQry" dbtype="query">
        SELECT DISTINCT associate, COUNT(*) AS associateCount FROM GetEmployeeInfo GROUP BY associate ORDER BY associate 
    </cfquery>
      <cfloop query="allAssociatesQry">
        <cfset thisAssociateName = trim(allAssociatesQry.associate) />
      <cfquery name="allLocCodeForAssociateQry" dbtype="query">
          SELECT trans_location,count(trans_location) AS locCntr FROM GetEmployeeInfo WHERE associate='#thisAssociateName#' GROUP BY trans_location ORDER BY trans_location
      </cfquery>
        <cfoutput query="allLocCodeForAssociateQry">
          <tr>
              <td><strong>#thisAssociateName#</strong></td>
              <!---<td><strong>#getop_id(192)#</strong></td>--->
              <td>#allLocCodeForAssociateQry.trans_location#</td>
              <td>#allLocCodeForAssociateQry.locCntr#</td>
              <td>#allAssociatesQry.associateCount#</td>
              <td>#NumberFormat((allLocCodeForAssociateQry.locCntr/allAssociatesQry.associateCount) * 100, '9.99')#%</td>
          </tr>
          <cfset thisAssociateName = "" />
      </cfoutput>
      </cfloop>
      <tr>
        <td><strong>Total</strong></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
      </tr>
    </tbody>
</table>

<cfcatch type="any"> 
        <cfset result.error = CFCATCH.message > 
        <cfset result.detail = CFCATCH.detail > 
    </cfcatch> 
</cftry>

我无法弄清楚如何更改我对第 4 列的查询,总计显示该位置的用户总清单,但我想要第 4 列中该位置的总清单。有人可以告诉我哪里出错了,以及如何找到这些位置的总数,而不是该位置的用户总数,该位置已经是第三列。

我可以在 add 之类的查询中进行查询吗

<cfquery datasource="#application.dsn#" name="GetLocationInfo">
        SELECT  *
        FROM    cl_checklists
        WHERE   date >=  <cfqueryparam value="#date1#" cfsqltype="cf_sql_timestamp" />
                AND date <= <cfqueryparam value="#date2#" cfsqltype="cf_sql_timestamp" />
                AND trans_location IN ( <cfqueryparam value="#FORM.location#" cfsqltype="cf_sql_varchar" list="true" />  )
    </cfquery>

然后在循环内添加另一个输出进行总计数?

【问题讨论】:

  • 每当我在&lt;cfloop&gt; 中看到查询时,我都会头晕目眩。是否可以通过单个查询对所有数据进行四舍五入?也许有一个 JOIN?
  • 为什么无法链接两个数据库服务器?从技术上讲,这是可能的。

标签: sql-server coldfusion group-by cfquery


【解决方案1】:

问题是您使用allAssociatesQry 作为您的第 4 列 'Checklist Generated By Selected Location(s)',它按 associate 分组,但您希望总清单计数您在此处的第 4 列将分组在 Location 而不是 Associate

您可能需要考虑将它们分开!

保持代码不变,只需在 allLocCodeForAssociateQry 查询之后添加一个单独的查询来计算第 4 列:

<cfquery name="allLocCountForAssociateQry" dbtype="query">
    SELECT trans_location,count(trans_location) AS totalLocCount FROM GetLocationInfo WHERE trans_location IS NOT NULL AND trans_location IN (#QuotedValueList(allLocCodeForAssociateQry.trans_location)#) GROUP BY trans_location
</cfquery>

现在在 cfoutput 查询循环中使用来自该查询的过滤值,用于 allLocCodeForAssociateQry,如下所示:

<cfoutput query="allLocCodeForAssociateQry">
  <tr>
      <td><strong>#thisAssociateName#</strong></td>
      <!---<td><strong>#getop_id(192)#</strong></td>--->
      <td>#allLocCodeForAssociateQry.trans_location#</td>
      <td>#allLocCodeForAssociateQry.locCntr#</td>
      <!--- Change 4th column to: --->
      <td>#allLocCountForAssociateQry['totalLocCount'][CurrentRow]#</td>
      <td>#NumberFormat((allLocCodeForAssociateQry.locCntr/allAssociatesQry.associateCount) * 100, '9.99')#%</td>
  </tr>
  <cfset thisAssociateName = "" />
</cfoutput>

更新:

David,根据我们在聊天中的讨论,您提到您希望显示每个 Associate 组结果的总数,并且您希望在报告结尾处汇总结果。

基于此,我发布了一个解决方案注意:我相信在cfloop 中使用分组会导致更简化和最佳的结果,但为了时间我选择了当前的工作解决方案。

我还添加了一堆 cmets 使其更具可读性和清晰性。

解决方法如下:

<cfset result = {} /> 
<cftry> 
    <cfset date1 = CREATEODBCDATETIME(form.StartDate & '00:00:00')>
    <cfset date2 = CREATEODBCDATETIME(form.EndDate & '23:59:59')>

    <cfquery datasource="#application.dsn#" name="GetEmployeeInfo">
        SELECT  *
        FROM    cl_checklists
        WHERE   date >=  <cfqueryparam value="#date1#" cfsqltype="cf_sql_timestamp" />
                AND date <= <cfqueryparam value="#date2#" cfsqltype="cf_sql_timestamp" />
                AND trans_location IN ( <cfqueryparam value="#FORM.location#" cfsqltype="cf_sql_varchar" list="true" />  )
                AND associate IN ( <cfqueryparam value="028,998,28" cfsqltype="cf_sql_varchar" list="true" />  )
    </cfquery>

    <cfquery datasource="#application.dsn#" name="GetLocationInfo">
        SELECT  *
        FROM    cl_checklists
        WHERE   date >=  <cfqueryparam value="#date1#" cfsqltype="cf_sql_timestamp" />
                AND date <= <cfqueryparam value="#date2#" cfsqltype="cf_sql_timestamp" />
                AND trans_location IN ( <cfqueryparam value="#FORM.location#" cfsqltype="cf_sql_varchar" list="true" />  )
    </cfquery>

     <cffunction name="getop_id" access="public" returntype="string"> 
        <cfargument name="associate"  > 
        <cfquery name="spitOutop_id" datasource="#application.userinfo_dsn#"> 
            SELECT assoc_name 
            FROM dbo.tco_associates 
            WHERE assoc_id= #arguments.associate# 
        </cfquery> 
        <cfreturn spitOutop_id.assoc_name > 
     </cffunction> 

     <cfquery name="allAssociatesQry" dbtype="query">
        SELECT DISTINCT associate, COUNT(*) AS associateCount FROM GetEmployeeInfo GROUP BY associate ORDER BY associate 
     </cfquery>

<table border="1" id="Checklist_Stats">
    <thead>
        <th><strong>Associate Name</strong></th>
        <th><strong>Location</strong></th>
        <th><strong>Checklists Generated by Associate</strong></th>
        <th><strong>Checklists Generated by Selected Location(s)</strong></th>
        <th><strong>Associate Percentage of Location Total</strong></th>   
    </thead>
    <tbody>
      <!--- aggregate variables --->
      <cfset aggrAssociateChecklist = 0>
      <cfset aggrLocationChecklist = 0>

      <cfloop query="allAssociatesQry">
          <!--- get Associate's name --->
          <cfset thisAssociateCode = trim(allAssociatesQry.associate)>
          <cfset thisAssociateName = getop_id(thisAssociateCode) />
          <!--- 1.1 get all trans_location code and total counts for the current Associate --->
          <cfquery name="allLocCodeForAssociateQry" dbtype="query">
              SELECT trans_location,count(trans_location) AS locCntr FROM GetEmployeeInfo WHERE associate='#thisAssociateCode#' GROUP BY trans_location ORDER BY trans_location
          </cfquery>
          <!--- 1.2 get the aggregate of checklist count generated by the current Associate for each location --->
          <cfquery name="qTotalChecklistCountForAssociate" dbtype="query">
              SELECT SUM(locCntr) AS totalAssocChecklist FROM allLocCodeForAssociateQry 
          </cfquery>

          <!--- 2.1 get the total location checklist for each location available for the current Associate --->
          <cfquery name="allLocChecklistForAssociateQry" dbtype="query">
              SELECT trans_location,count(trans_location) AS totalLocCount FROM GetLocationInfo WHERE trans_location IN (#QuotedValueList(allLocCodeForAssociateQry.trans_location)#) GROUP BY trans_location ORDER BY trans_location
          </cfquery>
          <!--- 2.2 get the aggregate of location checklist generated by the current Associate --->
          <cfquery name="qTotalLocChecklistForAssociate" dbtype="query">
              SELECT SUM(totalLocCount) AS totalLocChecklist FROM allLocChecklistForAssociateQry
          </cfquery>
          <!--- display record for the current Associate --->
            <cfoutput query="allLocCodeForAssociateQry">
              <tr>
                  <!---<td><strong>#thisAssociateCode#</strong></td>--->
                  <td><strong>#thisAssociateName#</strong></td>
                  <td>#allLocCodeForAssociateQry.trans_location#</td>
                  <td>#allLocCodeForAssociateQry.locCntr#</td>
                  <td>#allLocChecklistForAssociateQry['totalLocCount'][CurrentRow]#</td>
                  <td>#NumberFormat((allLocCodeForAssociateQry.locCntr/allLocChecklistForAssociateQry['totalLocCount'][CurrentRow]) * 100, '9.99')#%</td>
              </tr>
              <cfset thisAssociateName = "" />
            </cfoutput>
            <!--- 3.1 get sub total for each Associate group --->
            <cfset totalAssocChecklist = qTotalChecklistCountForAssociate.totalAssocChecklist>
            <cfset totalLocChecklist = qTotalLocChecklistForAssociate.totalLocChecklist>
            <!--- 3.2 add to the aggregate --->
            <cfset aggrAssociateChecklist += totalAssocChecklist>
            <cfset aggrLocationChecklist += totalLocChecklist>
            <!--- display sub total for each Associate group --->
            <cfoutput>
                <tr>
                    <td><strong>Subtotal</strong></td>
                    <td></td>
                    <td>#totalAssocChecklist#</td>
                    <td>#totalLocChecklist#</td>
                    <td>#NumberFormat((totalAssocChecklist/totalLocChecklist) * 100, '9.99')#%</td>
                </tr>
            </cfoutput>
      </cfloop>
      <!--- display calculated aggregate at the end of the result --->
      <cfoutput>
          <tr>
            <td><strong>Total</strong></td>
            <td></td>
            <td>#aggrAssociateChecklist#</td>
            <td>#aggrLocationChecklist#</td>
            <td>#NumberFormat((aggrAssociateChecklist/aggrLocationChecklist) * 100, '9.99')#%</td>
          </tr>
      </cfoutput>
    </tbody>
</table>
<cfcatch type="any"> 
        <cfset result.error = CFCATCH.message > 
        <cfset result.detail = CFCATCH.detail > 
    </cfcatch> 
</cftry>

【讨论】:

  • 啊!我想您必须匹配显示城市代码的顺序和totalLocCount 的顺序才能相同。
  • 我的意思是一样的@DavidBrierton。您能否发布新的查询结果以便更好地理解?
  • @DavidBrierton 我刚刚更新了我的答案,以包括您希望对结果集进行的更改,正如我们在聊天中讨论的那样。
  • 嗨@DavidBrierton 我已经更正了解决方案。再次检查结果。
  • @DavidBrierton 如果解决方案如您在聊天对话中提到的那样对您有效,请将其标记为已接受。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-26
  • 1970-01-01
  • 1970-01-01
  • 2016-02-26
  • 1970-01-01
  • 2013-03-04
  • 2012-05-07
相关资源
最近更新 更多