PHP中通过sqlsrv调用存储过程——成绩排名去除重复字段的数据行
培训考试项目中,需要实现考试成绩排名:排名参考项为分数(score降序)、参加日期(attendtime升序)、第几次参加考试(frequency升序);并且,每个用户只保留一条数据(pid)。
考试结果存储表格如下:
期望得到的结果为:
解决思路:
- 去重:
- 考虑到dintinct针对单个字段比较有效,结合其他字段使用时,效果不理想;
- 嵌套语句先进行排名,再去除重复的pid数据行;尝试半天没写出来;请教同学,由他给出下一条方案
- 使用临时表,分语句查询;先排名为temp1表,后在temp1表中删除分数小的重复的pid行,再删除考试次数大的重复的pid行,添加rankid字段结合其他字段生成新的temp2临时表;此方法经测试可行,创建为存储过程代码如下:
1 Create PROCEDURE [dbo].[myZhenxin] 2 @examid int 3 AS 4 BEGIN 5 if object_id('tempdb..#temp1') is not null 6 Begin 7 drop table #temp1 8 End 9 10 if object_id('tempdb..#temp2') is not null 11 Begin 12 drop table #temp2 13 End 14 15 -- Insert statements for procedure here 16 select id,frequency,attendtime, examid,score,pid into #temp1 from ExamResult where examid=@examid order by score desc,attendtime 17 18 delete #temp1 where id in(select a.id from #temp1 a, #temp1 b where a.pid = b.pid and a.score<b.score) 19 20 delete #temp1 where id in(select a.id from #temp1 a, #temp1 b where a.pid = b.pid and a.frequency>b.frequency ) 21 22 select IDENTITY(int,1,1) rankid, examid,pid,score,frequency,attendtime into #temp2 from #temp1 23 24 select * from #temp2 25 END
在sql server中,调用存储过程的语句为:
exec myZhenxin '11'
在php中使用sqlsrv调用存储过程:
- 直接使用sqlsrv_fetch_array()失败,调试显示没有结果行。
- 找到经验帖I have a Stored Procedure whose result set cannot be fetched by PHP web application.最后一位回答者当中推荐使用sqlsrv_next_result().
- 以下是该帖中该用户提出的解决方案,测试可行;
1 if ( ($stmt = sqlsrv_query($conn, $tsql)) ) 2 { 3 // now, iterate through all the statements in 4 // stored proc or script $tsql: 5 do 6 { 7 // process the result of the iteration 8 if ( sqlsrv_num_fields($stmt) > 0 ) 9 { 10 // we have a result set 11 while ( ($row=sqlsrv_fetch_array($stmt)) ) 12 { 13 // do something with $row 14 } 15 } 16 else 17 { 18 // we have something else 19 $rowsAffected = sqlsrv_rows_affected($stmt); 20 } 21 } while ( ($next = sqlsrv_next_result($stmt)) ) ; 22 23 if ( $next === NULL ) 24 { 25 // it worked 26 } 27 else 28 { 29 // it didn't work, check sqlsrv_errors() 30 } 31 32 sqlsrv_free_stmt($stmt); 33 }