0

这是我在 cfquery 输出之前的“employeeRatings”表中使用的 RAW DATA 示例:

        (showcasing employeeID:1128 for the month of May)

employeeID  |   Possible_Factor  |   Factor   |  ratingDate
=======================================================================
 1128       |        .1          |  .1        | 5/25/2013 2:05:13 PM 
 1128       |        .1          |  .0        | 5/22/2013 9:30:43 AM 
 1128       |        .2          |  .1        | 5/17/2013 9:42:09 AM 
 1128       |        .1          |  .1        | 5/13/2013 8:07:15 AM 
 1128       |        .1          |  .0        | 5/10/2013 7:52:51 AM 
 1128       |        .4          |  .0        | 5/6/2013 12:41:12 PM 

这是 cfquery(SQL 语句):

SELECT ROUND(100 * (SUM(Factor) / SUM(Possible_Factor)), 2) AS employeeRating, CONVERT(CHAR(4), ratingDate, 100) + CONVERT(CHAR(4), ratingDate, 120) AS month, employeeID, DATEADD(MONTH, DATEDIFF(MONTH, 0, ratingDate), 0) AS shortdate 
FROM employeeRatings
GROUP BY CONVERT(CHAR(4), ratingDate, 100) + CONVERT(CHAR(4), ratingDate, 120), DATEADD(MONTH, DATEDIFF(MONTH, 0, ratingDate), 0), employeeID 
ORDER BY employeeID, DATEADD(MONTH, DATEDIFF(MONTH, 0, ratingDate), 0) DESC

在 cfquery 之后,输出将如下所示:

employeeID  |   employeeRating   |   month      |  shortdate
=======================================================================
 1128       |        30          |  May 2013    | 5/1/2013 12:00:00 AM 
 1128       |        60          |  April 2013  | 4/1/2013 12:00:00 AM
 1128       |        90          |  Jan 2013    | 1/1/2013 12:00:00 AM
 7310000    |        95          |  April 2013  | 4/1/2013 12:00:00 AM
 7310000    |        85          |  Mar 2013    | 3/1/2013 12:00:00 AM
 7310000    |        75          |  Feb 2013    | 2/1/2013 12:00:00 AM
 7310000    |        55          |  Jan 2013    | 1/1/2013 12:00:00 AM
 444981     |        27          |  Mar 2013    | 3/1/2013 12:00:00 AM
 444981     |        77          |  Jan 2013    | 1/1/2013 12:00:00 AM
 444981     |        97          |  Nov 2012    | 11/1/2012 12:00:00 AM
 444981     |        37          |  Sept 2012   | 9/1/2012 12:00:00 AM
 444981     |        47          |  Aug 2012    | 8/1/2012 12:00:00 AM

我需要一个员工并列出他们最后三个评级(如果月份为空,则跳过空月份并获得下个月的评级,以展示最后三个记录的评级)。这是一个动态 cfquery,列出了 200 多名员工。以下是所需的输出:

supplierID  |   LastRating   |   SecondLastRating  |   ThirdLastRating
======================================================================
 1128       |        30      |       60            |         90
 7310000    |        95      |       85            |         75
 444981     |        27      |       77            |         97

我在 SQL Server 2000(兼容性 80)上使用 ColdFusion,但是我使用的 ColdFusion 版本不支持 cfloop 组属性。我想获取新的输出并将其放入一个新的查询中,以便它可以与另一个查询连接。一个解决方案 = 来自 FB 的星巴克礼物 ;) 谢谢大家的时间和考虑!!!!

4

3 回答 3

3

这是一个 ColdFusion 唯一的解决方案

<table>
<tr>
    <td>SupplierID</td>
    <td>LastRating</td>
    <td>SecondLastRating</td>
    <td>ThirdLastRating</td>
</tr>
<cfoutput name="qrySupplier" group="employeeID">
<cfset Rating  = 0>
<tr>
    <td>#employeeid#</td>
    <cfoutput>
       <cfset Rating++>
       <cfif Rating LTE 3>
           <td>#employeerating#</td>
       </cfif>
     </cfoutput>
</tr>
</cfoutput>
</table>
于 2013-06-05T15:23:09.163 回答
3

SQL Server 2005+

另一种选择是使用 SQL Server 的PIVOT运算符

首先使用ROW_NUMBER()按员工和日期对记录进行排名。(注意:如果您的表不包含实际的日期时间列,则可以替换标识列,或将“月份”转换为datetimeusing convert())。

    SELECT  employeeID
            , employeeRating
            , ROW_NUMBER() OVER ( 
                    PARTITION BY employeeID 
                    ORDER BY employeeID, theRatingDateCol DESC
            ) AS Row
    FROM   yourTable
    ...

结果:

employeeID  employeeRating Row
----------- -------------- --------------------
1128        30             1
1128        60             2
1128        90             3
444981      27             1
444981      77             2
444981      97             3
444981      37             4
7310000     95             1
7310000     85             2
7310000     75             3
7310000     55             4

然后PIVOT是前三 (3) 行的结果:

    ... 
    PIVOT
    (       
            MIN(employeeRating)
            FOR Row IN ( [1],[2],[3]) 
    )

完整查询:

SELECT pvt.employeeID
        , pvt.[1] AS LastRating  
        , pvt.[2] AS SecondLastRating  
        , pvt.[3] AS ThirdLastRating  
FROM (
        --- order by employee and rating date (descending)
        SELECT  employeeID
                , employeeRating
                , ROW_NUMBER() OVER ( 
                    PARTITION BY employeeID 
                    ORDER BY employeeID, theRatingDateCol DESC
                ) AS Row
        FROM   yourTable
    ) data
    PIVOT
    (   -- take top 3 values
        MIN(employeeRating)
        FOR Row IN ( [1],[2],[3]) 
    ) pvt

结果:

employeeID  LastRating  SecondLastRating ThirdLastRating
----------- ----------- ---------------- ---------------
1128        30          60               90
444981      27          77               97
7310000     95          85               75

SQL Server 2000

不幸的是,SQL Server 2000 和更早的版本不支持这些功能中的任何一个。PIVOT虽然不像CASE.

首先,使用子查询代替ROW_NUMBER(). 本质上,您count是评级日期较早的记录数,并使用它代替行号。注意:这假设每个员工的评级日期是唯一的。如果不是,您将需要添加另一列来打破平局。

然后使用CASE检查行号并为前三个记录生成列:

SELECT  r.employeeID
        , MAX( CASE WHEN r.Row = 0 THEN r.EmployeeRating ELSE 0 END ) AS LastRating  
        , MAX( CASE WHEN r.Row = 1 THEN r.EmployeeRating ELSE 0 END ) AS SecondLastRating  
        , MAX( CASE WHEN r.Row = 2 THEN r.EmployeeRating ELSE 0 END ) AS ThirdLastRating  
FROM  (
        SELECT  m.employeeID
                , m.employeeRating
                , m.theRatingDate
                , (  SELECT COUNT(*)
                     FROM   yourTable cnt
                    WHERE  cnt.employeeID = m.employeeID
                    AND    cnt.theRatingDate > m.theRatingDate
                ) AS Row
        FROM   yourTable m
        GROUP BY m.employeeID
            , m.employeeRating
            , m.theRatingDate
        ) r
WHERE  r.Row <= 2
GROUP BY r.employeeID

冷融合

最后一个选择是使用 ColdFusion。您可以调整James Mohler 的答案以填充单独的“枢轴”查询。在查询循环之前,创建一个新的查询对象,并按顺序命名评级列,即rating1,rating2,rating3. 在外部循环内,为每个员工添加一行。最后,使用计数器填充内部循环内的前三列。

注意:原始查询必须按顺序排序,employeeID, shortDate DESC否则代码将无法正常工作。

<cfset newQuery = queryNew("employeeID,rating1,rating2,rating3", "integer,Decimal,Decimal,Decimal")>

<cfoutput query="originalQuery" group="employeeID">
    <!--- add new employee row --->
    <cfset ratingRow = queryAddRow(newQuery, 1)>
    <cfset newQuery["employeeID"][ratingRow] = employeeID>

    <!--- initialize rating counter --->
    <cfset ratingIndex = 0>
    <cfoutput>
        <cfset ratingColumn++>
        <!--- populate top 3 rating columns --->
        <cfif ratingColumn lte 3>
            <cfset newQuery["rating"& ratingColumn][ratingRow] = employeeRating>
        </cfif>
    </cfoutput>
</cfoutput>
于 2013-06-06T01:14:25.243 回答
1

这里有一些你可以尝试让你开始的东西。我留下了评论。我没有权限建立一个快速表,所以它未经测试但可能是一个很好的开始。我考虑到您的员工/供应商的评分可能多于或少于 3 个。

<!--- Counter to count ratings  --->
<Cfset x=0>
<table width="600" border="0" cellspacing="0" cellpadding="0">
  <tr>
    <td>supplierid</td>
    <td>last rating</td>
    <td>second last rating</td>
    <td>thirdlastrating</td>
  </tr>
<!--- Group by employee --->
<cfoutput query="yourQuery" group="employeeid">
    <!--- if previous employee had less then 3 ratings, close off table --->
    <cfif x gt 0 and x lt 3>
         <cfif x eq 1><td>&nbsp</td><td>&nbsp;</td></tr></cfif>
         <cfif x eq 2><td>&nbsp;</td></tr></cfif>
    </cfif>
    <!--- Loop through employee --->
  <tr>
    <td>#employeeid#</td>
    <!--- Check counter to make sure we are only doing 3 ratings per line --->
    <cfif x lt 3>
        <cfoutput>
        <td>#employeerating#</td>
        <cfset x=x+1>
        </cfoutput>
    </cfif>
    <!--- If at the 3rd rating, close off the row --->
    <cfif x eq 3>
        </tr>
        <cfset x=0>
        <!--- if at 3rd rating, reset counter --->
    </cfif>
</cfoutput>
</table>
于 2013-06-05T15:20:00.140 回答