2017-06-30 3 views
1

Ich versuche, eine Zeit für den Fall verstreichen, wenn cd.result = 'übergeben'. Ich kann es nicht in die Wo-Bedingung schreiben, weil ich die anderen Spalten für alle Bedingungen erscheinen lassen muss, nicht nur Situationen passieren. Ich habe versucht, dies in einem Subselect zu tun, aber es scheint ewig dauern, um auszuführen (35 min und zählen).Erhalten Sie einen Durchschnitt für eine Spalte in SQL-Abfrage

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 

meinen Versuch mit subselect der Arbeit viel zu langsam und nicht am Ende ist:

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 

so mein Ziel, eine Spalte hinzuzufügen ist, dass der Mittelwert avg_time_sec für die mit der cd.result = 'pass'. Ich habe ein paar Versionen ausprobiert, aber ich bin ratlos.

+0

Was soll es sein, wenn es nicht 'Pass' ist? Können Sie auch einige Beispieldaten hinzufügen, um zu veranschaulichen, was Sie tun möchten? Es hört sich so an, als müssten Sie nur die CASE-Logik verwenden, die Sie mit den Spalten "SUM()" gemacht haben. – Siyual

+0

Ich möchte nur eine Spalte für die durchschnittliche Zeit für Personen hinzufügen, die den Rest des Kanals verlassen haben Säulen. Die Nicht-Pass-Leute würden in dieser Spalte ignoriert werden. –

+0

'Round (Durchschn. (Fall, wenn cd.result = 'Pass', dann CAST (time_elapsed als float)/1000 Else Null End, 3))'? – Siyual

Antwort

1

haben yoy versucht, so etwas wie:

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

Als richtig markiert, weil ich glaube, dass Sie zuerst waren. –

1

Hilft ein 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 

Edit: So kann man nur auf einer nicht indizierten Tabelle ausgeführt wird (TEMP) einmal statt viele Male auf der Unterabfrage.

+0

Große Antwort auch, das oben genannte ist wahrscheinlich einfacher für Mid-Level-Leute wie mich. Upvoted und vielen Dank für Ihre Zeit. –

+0

Ich stimme zu. @Serg hat eine gute und einfachere Antwort, die ich übersehen habe! – justiceorjustus

1

Compute bedingte Avg erfüllungs sum/bedingte Zählung

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

Perfekt. Danke. –

+0

PS Ich habe nur die andere Antwort als richtig gewählt, weil ich glaube, dass er zuerst war, obwohl er wegen der geringeren Representation nach unten gedrückt wurde. –

+0

Kein Problem. :) BTW, diese Antwort ist besser, wirklich Avg wird es für dich tun. – Serg

1

In dieser Situation können Sie von CASE-Anweisungen wegdreht und verwenden UNION aggregieren dann die Ergebnis - es sollte viel schneller sein.

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 
Verwandte Themen