列组上的SUM

时间:2011-09-21 12:27:32

标签: sql sql-server-2005

我有三个表格,结构类似

tasktime - starttime,endtime,packagedetailid,packageid
packagedetailid - packageid,productid, etc
productime - productid and searchesperday

我正在使用的查询如下

SELECT CONVERT(varchar, t.StartTime, 111) AS 'Date'
, SUM(DATEDIFF(second, t.StartTime, t.EndTime)) / 60 AS DailyMinutes
, COUNT(DISTINCT p.PackageDetailID) AS OrderCount
, LEFT(CAST(SUM(DATEDIFF(minute, t.StartTime, t.EndTime))
     / (COUNT(DISTINCT p.PackageDetailID) + 0.0000001) AS varchar), 4) AS PerOrder
, LEFT(CAST((COUNT(DISTINCT p.PackageDetailID) * 100)
     / (e.SearchesPerDay + 0.00000001) AS varchar), 4) AS WeightedOrderCount
FROM  ProductTime AS e INNER JOIN dbo.PackageDetails AS p
 WITH (NOLOCK) ON e.ProductID = p.ProductID INNER JOIN 
TaskTime AS t WITH (NOLOCK) ON p.PackageDetailID = t.PackageDetailId
WHERE(t.EndTime IS NOT NULL) 
AND (DATEDIFF(hour, t.StartTime, t.EndTime) < 1) 
AND (DATEDIFF(second, t.StartTime, t.EndTime) > 0) 
AND (t.UserId = '12345') 
AND (t.StartTime BETWEEN '1/1/2010'
AND '9/13/2010')
GROUP BY CONVERT(varchar, t.StartTime, 111), e.SearchesPerDay
ORDER BY CONVERT(varchar, t.StartTime, 111)

OUTPUT是:

**date         dailyminutes  ordercount  perorder  weightordercount**

2010/01/04     104                26    4.03    43.30
2010/01/04     10                  1    9.99     1.24
2010/01/04     19                  8    2.37     8.88
2010/01/04     22                 11    1.99    10.90
2010/01/04     18                  5    3.59     2.77
2010/01/05     49                 17    2.99    28.30
2010/01/05     31                  5    6.39     5.55
2010/01/05     26                  6    4.33     5.99
2010/01/05      8                  4    1.99     3.33

但是我希望将日期"Weightordercount"与日期相加,以便输出

**date            dailyminutes  ordercount  perorder  weightordercount**

2010/01/04         173           51     21.97       67.09
2010/01/05         114           32     15.70       43.17

我不是SQL专家,如果可以通过单个SQL命令或通过Strored Procedure实现这一点,那么需要您的帮助

提前致谢

2 个答案:

答案 0 :(得分:3)

你的帖子中的代码格式很糟糕,所以我会给你一个通用答案:

您需要使用GROUP BY子句,然后使用SUM每个聚合。

这样的事情:

select date, sum(dailyminutes), sum(ordercount), sum(perorder), sum(weightordercount)
from (yourentirequery) a
group by date
order by date asc

答案 1 :(得分:1)

(1)Don't use varchar without length - 但为什么要转换为varchar?

(2)为什么每天按搜索分组?我猜这需要成为一个有意义的SUM,这就是我要做的:

;WITH x AS
(
    SELECT 
        [Date]         = DATEDIFF(DAY, '19000101', t.StartTime),
        DailyMinutes   = SUM(DATEDIFF(SECOND, t.StartTime, t.EndTime)),
        OrderCount     = COUNT(DISTINCT p.PackageDetailID),
        SearchesPerDay = SUM(e.SearchesPerDay)
    FROM 
        dbo.ProductTime AS e
    INNER JOIN 
        dbo.PackageDetails AS p
        ON e.ProductID = p.ProductID
    INNER JOIN 
        dbo.TaskTime AS t
        ON p.PackageDetailID = t.PackageDetailID
    WHERE 
        t.EndTime IS NOT NULL
        AND (DATEDIFF(SECOND, t.StartTime, t.EndTime) BETWEEN 1 AND 3599) 
        AND (t.UserId = '12345') 
        AND (t.StartTime >= '20100101' AND t.StartTime <= '20100913')
    GROUP BY 
        DATEDIFF(DAY, '19000101', t.StartTime)
)
SELECT 
    [Date] = DATEADD(DAY, [Date], '19000101'),
    DailyMinutes,
    OrderCount,
    PerOrder = CONVERT(DECIMAL(10,2), (DailyMinutes * 1.0 / OrderCount)),
    WeightedOrderCount = CONVERT(DECIMAL(10,2), (100.0 * OrderCount / SearchesPerDay))
FROM
    x
ORDER BY
    [Date];

其他一些增强功能:

(a)不要将BETWEEN用于日期/时间,请使用&gt; =和&lt; (我把结尾留作&lt; =但它可能意味着&lt; 9/14或&lt; 9/13)。

(b)不要使用区域格式作为日期 - &#39; 09/13/2010&#39;不是有效日期,具体取决于语言,日期格式或区域设置。 &#39; YYYYMMDD&#39;是SQL Server中仅用于日期的最安全的格式。

(c)尝试尽可能少地进行计算 - 我将重复计算移动到CTE中,以便其他计算中的参考可以更简单。您不需要CTE,也可以使用子查询。这也是我将两个检查与StartTime和EndTime之间的增量相结合的原因。

(d)获取小数的方法相当粗糙 - 添加小数位,转换为字符串,左侧...