获取sql查询中一列的平均值

时间:2017-06-30 20:01:13

标签: sql sql-server tsql

我正试图在cd.result =' Pass'时对案件的时间进行过度调整。我不能把它放在where条件中,因为我需要其他列出现在所有条件下,而不仅仅是通过情境。我尝试在子选择中执行此操作,但似乎需要永远执行(35分钟和计数)。

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

我的subselect尝试太慢了,可能不会最终工作:

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

所以我的目标是为那些使用cd.result =' pass'的人添加一个平均avg_time_sec的列。我尝试了几个版本,但我很难过。

4 个答案:

答案 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)上运行一次,而不是在子查询上运行很多次。

答案 1 :(得分: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

答案 2 :(得分: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

答案 3 :(得分: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