2017-06-30 55 views
1

我试图在cd.result ='Pass'的情况下得到大量时间流逝的情况。我不能把它放在哪里,因为我需要其他列出现所有条件,而不仅仅是通过情况。我试图在次选中做到这一点,但似乎需要永远执行(35分钟和计数)。在sql查询中获取一列的平均值

select ctir.item_dbkey, item_id 
    ,ctir.portion_id 
    ,Round(avg(CAST(time_elapsed as float)/1000), 3) as Avg_Time_Sec 
    ,SUM(CASE when cd.result = 'Pass' Then 1 Else 0 END) as N_PASS 
    ,SUM(CASE when cd.result = 'Fail' Then 1 Else 0 END) as N_FAIL 
    ,count(ctir.testassignment_ID)as N_Total 
from candidate_testItem_response ctir 
join [dbo].[Candidate_TestAssignment_Portion] ctil on ctir.TestAssignment_ID = ctil.TestAssignment_ID and ctir.portion_id = ctil.portion_ID 
join item_bank ib on ctir.item_dbkey = ib.item_dbkey 
join candidate_data cd on ctir.testassignment_id = cd.TestAssignment_ID and ctir.Portion_ID = cd.Portion_ID 
where ctir.portion_id = 15780 
    and ctil.start_time >= '2017-01-01 00:00:00.000'  
group by ctir.item_dbkey, ctir.Portion_ID, item_id 

我与子查询的尝试是过于缓慢,并可能最终不会工作:

select ctir.item_dbkey, item_id 
    ,ctir.portion_id 
    ,(select Round(avg(CAST(time_elapsed as float)/1000), 3) as Avg_Time_Sec 
     from candidate_testItem_response ctir 
     join candidate_data cd on ctir.testassignment_id = cd.TestAssignment_ID and ctir.Portion_ID = cd.Portion_ID 
     where cd.result = 'pass') 
    ,SUM(CASE when cd.result = 'Pass' Then 1 Else 0 END) as N_PASS 
    ,SUM(CASE when cd.result = 'Fail' Then 1 Else 0 END) as N_FAIL 
    ,count(ctir.testassignment_ID) as N_Total 

from candidate_testItem_response ctir 
join [dbo].[Candidate_TestAssignment_Portion] ctil on ctir.TestAssignment_ID = ctil.TestAssignment_ID and ctir.portion_id = ctil.portion_ID 
join item_bank ib on ctir.item_dbkey = ib.item_dbkey 
join candidate_data cd on ctir.testassignment_id = cd.TestAssignment_ID and ctir.Portion_ID = cd.Portion_ID 
where ctir.portion_id = 15780 
and ctil.start_time >= '2017-01-01 00:00:00.000' 

group by ctir.item_dbkey, ctir.Portion_ID, item_id 

,所以我的目标是要增加一列,平均的avg_time_sec对于那些与cd.result ='通过'。我尝试了几个版本,但我很难过。

+0

当它不是'Pass'时,你希望它是什么?你还可以添加一些示例数据来说明你想要做什么?这听起来像你只需要做与'SUM()'列一样的'CASE'逻辑... – Siyual

+0

我只想为通过的人添加一个平均时间的列,而剩下的列。该栏中的不合格人员将被忽略。 –

+0

'Round(Avg(Case when CD.result ='Pass'Then CAST(time_elapsed as float)/ 1000 Else Null End,3))'? – Siyual

回答

1

已经同比想是这样:

select ctir.item_dbkey, item_id, ctir.portion_id 
    ,Round(avg(
     CASE when cd.result = 'Pass' 
     THEN CAST(time_elapsed as float)/1000 
     ELSE null END), 3) as Avg_Time_Sec 
    ,SUM(CASE when cd.result = 'Pass' Then 1 Else 0 END) as N_PASS 
    ,SUM(CASE when cd.result = 'Fail' Then 1 Else 0 END) as N_FAIL 
    ,count(ctir.testassignment_ID)as N_Total 
from candidate_testItem_response ctir 
    join [dbo].[Candidate_TestAssignment_Portion] ctil on ctir.TestAssignment_ID = ctil.TestAssignment_ID and ctir.portion_id = ctil.portion_ID 
    join item_bank ib on ctir.item_dbkey = ib.item_dbkey 
    join candidate_data cd on ctir.testassignment_id = cd.TestAssignment_ID and ctir.Portion_ID = cd.Portion_ID 
where ctir.portion_id = 15780 
    and ctil.start_time >= '2017-01-01 00:00:00.000' 
group by ctir.item_dbkey, ctir.Portion_ID, item_id 
+0

标记为正确,因为我相信你是第一个。 –

1

CTE有帮助吗?

WITH TEMP 
AS (
    SELECT ctir.item_dbkey 
     ,item_id 
     ,ctir.portion_id 
     ,ctir.testassignment_id 
     ,SUM(CASE 
       WHEN cd.result = 'Pass' 
        THEN 1 
       ELSE 0 
       END) AS N_PASS 
     ,SUM(CASE 
       WHEN cd.result = 'Fail' 
        THEN 1 
       ELSE 0 
       END) AS N_FAIL 
     ,count(ctir.testassignment_ID) AS N_Total 
    FROM candidate_testItem_response ctir 
    JOIN [dbo].[Candidate_TestAssignment_Portion] ctil ON ctir.TestAssignment_ID = ctil.TestAssignment_ID 
     AND ctir.portion_id = ctil.portion_ID 
    JOIN item_bank ib ON ctir.item_dbkey = ib.item_dbkey 
    JOIN candidate_data cd ON ctir.testassignment_id = cd.TestAssignment_ID 
     AND ctir.Portion_ID = cd.Portion_ID 
    WHERE ctir.portion_id = 15780 
     AND ctil.start_time >= '2017-01-01 00:00:00.000' 
    GROUP BY ctir.item_dbkey 
     ,ctir.Portion_ID 
     ,item_id 
    ) 
SELECT t.item_dbkey 
    ,t.item_id 
    ,t.portion_id 
    ,t.N_PASS 
    ,t.N_FAIL 
    ,t.N_TOTAL 
    ,Round(avg(CAST(ctir.time_elapsed AS FLOAT)/1000), 3) AS Avg_Time_Sec 
FROM TEMP t 
LEFT JOIN candidate_testItem_response ctir 
JOIN candidate_data cd ON ctir.testassignment_id = t.TestAssignment_ID 
    AND ctir.Portion_ID = t.Portion_ID 
WHERE cd.result = 'pass' 
GROUP BY t.item_dbkey 
,t.item_id 
,t.portion_id 
,t.N_PASS 
,t.N_FAIL 
,t.N_TOTAL 

编辑:这样你就只在一个非索引表(您的TEMP)一次,而不是大量的在你的子查询时间运行。

+0

伟大的答案,以上可能更简单的像我这样的中层人士。 Upvoted,非常感谢你的时间。 –

+0

我同意。 @Serg有一个我忽略的更好更简单的答案! – justiceorjustus

1

计算条件平均为条件的总和/有条件计数

select ctir.item_dbkey, item_id 
    ,ctir.portion_id 
    ,Round(SUM(CASE when cd.result = 'Pass' THEN CAST(time_elapsed as float)/1000 END)/COUNT(CASE when cd.result = 'Pass' THEN 1 END), 3) as Avg_Time_Sec 
    ,SUM(CASE when cd.result = 'Pass' Then 1 Else 0 END) as N_PASS 
    ,SUM(CASE when cd.result = 'Fail' Then 1 Else 0 END) as N_FAIL 
    ,count(ctir.testassignment_ID)as N_Total 
from candidate_testItem_response ctir 
join [dbo].[Candidate_TestAssignment_Portion] ctil on ctir.TestAssignment_ID = ctil.TestAssignment_ID and ctir.portion_id = ctil.portion_ID 
join item_bank ib on ctir.item_dbkey = ib.item_dbkey 
join candidate_data cd on ctir.testassignment_id = cd.TestAssignment_ID and ctir.Portion_ID = cd.Portion_ID 
where ctir.portion_id = 15780 
    and ctil.start_time >= '2017-01-01 00:00:00.000'  

group by ctir.item_dbkey, ctir.Portion_ID, item_id 
+0

完美。谢谢。 –

+0

PS我只选择了其他答案,因为我相信他是第一个,但由于代表低而被推倒。 –

+0

没问题。 :)顺便说一句,那些答案是更好的,真正的平均值会为你做。 – Serg

1

在这种情况下,你可以从CASE语句改变方向走,并使用UNION然后汇总结果 - 它应该更快。

SELECT 
    item_dbkey, 
    item_id, 
    portion_id, 
    MAX(Avg_Time_Sec) AS Avg_Time_Sec, 
    SUM(n_pass) AS N_PASS, 
    SUM(n_fail) AS N_FAIL, 
    SUM(n_pass) + SUM(n_fail) AS N_Total 
FROM 
    (
    SELECT 
     ctir.item_dbkey, 
     item_id, 
     ctir.Portion_ID, 
     ROUND(AVG(CAST(time_elapsed AS FLOAT)/1000), 3) as Avg_Time_Sec, 
     COUNT(1) AS N_PASS, 
     0 AS N_FAIL 
    FROM 
     candidate_testItem_response AS ctir 
     join [dbo].[Candidate_TestAssignment_Portion] AS ctil 
     on ctir.TestAssignment_ID = ctil.TestAssignment_ID and ctir.portion_id = ctil.portion_ID 
     join item_bank AS ib 
     on ctir.item_dbkey = ib.item_dbkey 
     join candidate_data AS cd 
     on ctir.testassignment_id = cd.TestAssignment_ID and ctir.Portion_ID = cd.Portion_ID 
    WHERE 
     ctir.portion_id = 15780 AND 
     cd.result = 'Pass' AND 
     ctil.start_time >= '2017-01-01 00:00:00.000'  
    GROUP BY 
     ctir.item_dbkey, 
     item_id, 
     ctir.Portion_ID 
    UNION 
    SELECT 
     ctir.item_dbkey, 
     item_id, 
     ctir.Portion_ID, 
     0 AS Avg_Time_Sec, 
     0 AS N_PASS, 
     COUNT(1) AS N_FAIL 
    FROM 
     candidate_testItem_response AS ctir 
     join [dbo].[Candidate_TestAssignment_Portion] AS ctil 
     on ctir.TestAssignment_ID = ctil.TestAssignment_ID and ctir.portion_id = ctil.portion_ID 
     join item_bank AS ib 
     on ctir.item_dbkey = ib.item_dbkey 
     join candidate_data AS cd 
     on ctir.testassignment_id = cd.TestAssignment_ID and ctir.Portion_ID = cd.Portion_ID 
    WHERE 
     ctir.portion_id = 15780 AND 
     cd.result = 'Fail' AND 
     ctil.start_time >= '2017-01-01 00:00:00.000'  
    GROUP BY 
     ctir.item_dbkey, 
     item_id, 
     ctir.Portion_ID 
) AS inner_query 
GROUP BY 
    item_dbkey, 
    item_id, 
    portion_id