查询中的SQL SUM和按副本分组

时间:2013-03-20 21:58:29

标签: sql function sum aggregate-functions alias

以下是场景:

表: 的 CallMain:

Call_ID = PK(INT) 放弃(INT)1或NULL

CallHold:

Hold_ID = PK(INT)

Call_ID = FK(INT)

StartTime(INT)

EndTime(INT)

CallMain表中保存的每个调用都可以包含1,0或许多保留记录。每次呼叫保持时,FK都会创建一个记录,其中包含保持的开始时间和保持的结束时间。

现在,要在查询中返回此信息以显示调用及其总保持时间,我相信SQL如下:

SELECT CallMain.Call_ID, CallMain.Abandoned,  
ISNULL((CallHold.EndTime - CallHold.StartTime),0) AS HoldPeriodSeconds 
FROM CTIStatCall 
LEFT OUTER JOIN CallHold ON CallMain.Call_ID = CallHold.Call_ID

此查询应返回没有与之关联的保留记录的调用记录,并应将其作为NULLS返回。具有单个保留记录的呼叫正确显示。 LEFT OUTER JOIN返回的NULLS正在使用ISNULL()函数进行管理,并被替换为零,因为调用没有保持时间。

我的问题是,如果一个呼叫有多个保持记录,它将在结果中出现两次,即: Call_ID,HoldPeriod

212,254

213,154

214,158

214,25

214,10 从上面可以看出,Call 214有多个保持记录,共计193.我发现查询必须是:

SELECT
    CallMain.Call_ID,
    CallMain.Abandoned,  
    Sum(ISNULL((CallHold.EndTime - CallHold.StartTime), 0)) AS HoldPeriodSeconds 
FROM
    CallMain
LEFT OUTER JOIN
    CallHold
ON
    CallMain.Call_ID = CallHold.Call_ID
GROUP BY
    CallMain.Call_ID,
    CallMain.Abandoned

我现在的问题是我在MainCall表中还有其他列也将被返回,CallStart,CallAns,CallEnd以及这些列用于计算其他一些派生值。我正在返回这些并将它们添加到group by子句中,但它会再次显示重复值。我怎样才能解决这个问题?

我已经尝试过:

SELECT CallMain.Call_ID, dateadd(s,CallMain.StartTime, '1970-01-01') AS StartTime,
dateadd(s,CallMain.AnsTime, '1970-01-01') AS AnsTime, 
dateadd(s,CallMain.EndTime, '1970-01-01') AS EndTime,
CallMain.Abandoned,
(CallMain.AnsTime - CallMain.StartTime) AS RingPeriod,
SUM(ISNULL((CallHold.EndTime - CallHold.StartTime),0)) AS HoldPeriod,
(CallMain.EndTime - CallMain.AnsTime) - ISNULL((CallHold.EndTime - CallHold.StartTime),0) AS TalkPeriod
FROM CallMain
LEFT OUTER JOIN
CallHold ON CallMain.Call_ID = CallHold.Call_ID
   GROUP BY CallMain.Call_ID, CallMain.Abandoned, CallMain.StartTime, CallMain.EndTime, CallMain.AnsTime, CallHold.EndTime, CallHold.StartTime 
     

通过CallMain.Call_ID订购

2 个答案:

答案 0 :(得分:0)

正如你自己已经说过的那样。当您按CallStartCallAnsCallEnd分组时,会收到多个结果。这意味着每个Call_ID, Abandoned组合的这些列的唯一值都超过1个。

您必须决定要显示哪些值。例如,您可以选择采用如下最大值:

SELECT
    CallMain.Call_ID,
    CallMain.Abandoned,  
    Sum(ISNULL((CallHold.EndTime - CallHold.StartTime), 0)) AS HoldPeriodSeconds,
    (MAX(CallMain.AnsTime) - MAX(CallMain.StartTime)) AS RingPeriod,
    ....
FROM
    CallMain
LEFT OUTER JOIN
    CallHold
ON
    CallMain.Call_ID = CallHold.Call_ID
GROUP BY
    CallMain.Call_ID,
    CallMain.Abandoned

或者,或许更符合逻辑,使用{Hold}中的SUM函数。我不知道你期待什么结果。

答案 1 :(得分:0)

这是因为你正在分组

CallHold.EndTime , CallHold.StartTime

由于您在CallMain中每个条目获得一行,因此会返回多个条目。这些需要从组中删除,并从select语句或使用的合适的聚合函数中删除。它应该是这样的......

SELECT CallMain.Call_ID, dateadd(s,CallMain.StartTime, '1970-01-01') AS StartTime,
       dateadd(s,CallMain.AnsTime, '1970-01-01') AS AnsTime, 
       dateadd(s,CallMain.EndTime, '1970-01-01') AS EndTime,
       CallMain.Abandoned,
       (CallMain.AnsTime - CallMain.StartTime) AS RingPeriod,
       SUM(ISNULL((CallHold.EndTime - CallHold.StartTime),0)) AS HoldPeriod,
       (CallMain.EndTime - CallMain.AnsTime) - ISNULL((CallHold.EndTime - CallHold.StartTime),0) AS TalkPeriod
  FROM CallMain
LEFT OUTER JOIN
       CallHold ON CallMain.Call_ID = CallHold.Call_ID
GROUP BY CallMain.Call_ID, CallMain.Abandoned, CallMain.StartTime, CallMain.EndTime, CallMain.AnsTime