SUM on a Column Group
i have three tables with structure something like
tasktime - starttime,endtime,packagedetailid,packageid
packagedetailid - packageid,productid, etc
productime - productid and searchesperday
and the query i am using on these is as follows
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) &开发者_开发问答lt; 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)
The OUTPUT is:
**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
But i want to SUM up the "Weightordercount"
against the date so that the output is
**date dailyminutes ordercount perorder weightordercount**
2010/01/04 173 51 21.97 67.09
2010/01/05 114 32 15.70 43.17
i am not a sql expert and need your help if this can be achieved by a Single SQL command or through a Strored Procedure
Thanks in advance
Your code is horribly formatted in your post, so I'm going to give you a general answer:
You need to use a GROUP BY
clause and then SUM
each of your aggregates.
So something like this:
select date, sum(dailyminutes), sum(ordercount), sum(perorder), sum(weightordercount)
from (yourentirequery) a
group by date
order by date asc
(1) Don't use varchar without length - but why are you converting to a varchar anyway?
(2) Why are you grouping by searches per day? I'm guessing this needs to be a SUM to be meaningful, here is how I would do it:
;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 couple of other enhancements:
(a) don't use BETWEEN for date/time, use >= and < (I left the end as <= but it's likely you either meant < 9/14 or < 9/13).
(b) don't use regional formats for dates - '09/13/2010' is not a valid date depending on language, dateformat or regional settings. 'YYYYMMDD' is the safest format to use in SQL Server for date only.
(c) try to perform calculations as few times as possible - I moved repeated calculations into a CTE so that reference in other calculations can be much simpler. You don't need a CTE, you can also use a subquery. This is also the reason I combined the two checks against the delta between StartTime and EndTime.
(d) your method for getting decimals was rather crude - adding decimal places, converting to a string, taking the left...
精彩评论