Sql COLDFUSION:如何按第一列分组并将第二列转换为三个独立的列
这是我在cfquery输出之前处理的“employeeRatings”表中的原始数据示例:Sql COLDFUSION:如何按第一列分组并将第二列转换为三个独立的列,sql,sql-server,coldfusion,pivot,cfloop,Sql,Sql Server,Coldfusion,Pivot,Cfloop,这是我在cfquery输出之前处理的“employeeRatings”表中的原始数据示例: (showcasing employeeID:1128 for the month of May) employeeID | Possible_Factor | Factor | ratingDate ======================================================================= 1128 |
(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语句):
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 group属性。我想获取新的输出并将其放入一个新的查询中,这样它就可以与另一个查询连接起来。解决方案=来自FB的星巴克礼品;)谢谢大家的时间和考虑 以下是一些你可以尝试开始的东西。我留下了评论。我没有机会建立一个快速表,所以它未经测试,但可能是一个很好的开端。我考虑到您的员工/供应商的评级可能高于或低于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> </td><td> </td></tr></cfif>
<cfif x eq 2><td> </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>
供应商
最后评级
倒数第二名
第三流
 
#雇员ID#
#就业#
以下是一些您可以尝试开始的内容。我留下了评论。我没有机会建立一个快速表,所以它未经测试,但可能是一个很好的开端。我考虑到您的员工/供应商的评级可能高于或低于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> </td><td> </td></tr></cfif>
<cfif x eq 2><td> </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>
供应商
最后评级
倒数第二名
第三流
 
#雇员ID#
#就业#
这里是一个仅适用于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>
供应商
最后评级
第二级
第三流
#雇员ID#
#就业#
这里是一个仅适用于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>
供应商
最后评级
第二级
第三流
#雇员ID#
#就业#
SQL Server 2005+
另一种选择是使用SQL Server的运算符
首次使用按员工和日期对记录进行排序。(注意:如果表中不包含实际日期时间列,则可以替换标识列,或使用convert()
将“月”转换为datetime
)
结果:
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
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
然后PIVOT
前三(3)行的结果:
完整查询:
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
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
结果:
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
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
不幸的是,SQLServer2000和更早版本都不支持这两种功能。虽然不像PIVOT
那样流畅,但您仍然可以使用子查询和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
SQL Server 2005+
另一种选择是使用SQL Server的运算符
首次使用按员工和日期对记录进行排序。(注意:如果表中不包含实际日期时间列,则可以替换标识列,或使用convert()
将“月”转换为datetime
)
结果:
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
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
然后PIVOT
前三(3)行的结果:
完整查询:
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
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
结果:
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
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
不幸的是,SQLServer2000和更早版本都不支持这两种功能。虽然不像PIVOT
那样流畅,但您仍然可以使用子查询和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
您使用的是哪种DBMS?不是分组cfloop使用分组cfoutput,而是在CFIs的所有版本中都有效的修改原始db查询选项?如果是,请更新问题标签以指示您的数据库类型/版本。您好!首先,感谢大家花时间回顾我的问题。@Miguel-F,我使用的是MS SQL Server。您使用的是哪种DBMS?使用分组cfloop而不是分组cfoutput,在所有版本的CFIs中都有效修改原始db查询选项?如果是,请更新问题标签以指示您的数据库类型/版本。您好!首先,感谢大家花时间回顾我的问题。@Miguel-F,我正在使用MS SQL Server。这很有效!!!!!!我正在使用它!!!!非常感谢你!!!这对我来说是困难的一部分,但现在我将看到我可以基于此创建一个新的查询。不管我会在FB和星巴克上找到你,再次感谢你!现在,我想弄明白的技巧是如何利用它并创建一个新的查询。建议呢?一个数据透视表useful@Enchauva-在这种特定情况下,在2000年模拟pivot会有点难看/难以管理-除非您能够创建视图或临时表。你…吗?虽然不理想,但仍然可以使用CF代码。看看我的最新答案。这很有效!!!!!!我正在使用它!!