I have two tables:
DepotSessions: ID (int), Date (date), StartTime (int), EndTime (int), TruckID (int)
DepotSessionDetails: ID (int), DepotSessionID (int), Status (varchar(20)), Duration (int)
I need to know how many times each truck was loaded (TotalLoadCount), how long it was loaded (TotalLoadTime) and how much time it spent in the depot (TotalDepotTime).
There can be multiple DepotSessionRows for a given TruckID and Date. Also, there can be multiple DepotSessionDetails rows for a given DepotSessionID.
Some sample data:
DepotSessions:
ID TruckID Date StartTime EndTime
-----------------------------------------------
1 1 '2013-04-01' 500 3000
2 1 '2013-04-01' 14000 25000
DepotSessionDetails:
ID DepotSessionID Status Duration
------------------------------------------
1 1 'Waiting' 40
2 1 'Loading' 25
3 1 'Waiting' 33
4 1 'Loading' 38
5 2 'Waiting' 100
6 2 'Loading' 167
7 2 'Waiting' 420
8 2 'Loading' 980
Based on this sample data, I need to get:
TotalDepotTime 13500 (as in 25000 - 14000 + 3000 - 500)
TotalLoadTime 1210
TotalLoadCount 4
Here's what I have at the moment:
SELECT
DS.Date, DS.TruckID,
MIN(DS.StartTime), MAX(DS.EndTime),
SUM(DS.EndTime-DS.StartTime) TotalDepotTime,
SUM(CASE WHEN DSD.Status = 'Loading' THEN DSD.Duration ELSE 0 END) TotalLoadTime,
COUNT(CASE DSD.Status = 'Loading' THEN 1 ELSE 0 END) TotalLoadCount
FROM
DepotSessions DS
INNER JOIN
DepotSessionDetails DSD on DS.ID = DSD.DepotSessionID
GROUP BY
Date, TruckID
TotalDepotTime 54000 (incorrect, should be 13500)
TotalLoadTime 1210
TotalLoadCount 8 (incorrect, should be 4)
Try this:
SELECT DS.Date, DS.TruckID,
MIN(DS.StartTime), MAX(DS.EndTime),
sum(distinct(DS.EndTime))-sum(distinct(DS.StartTime)) as TotalDepotTime,
SUM( CASE DSD.Status WHEN 'Loading' THEN DSD.Duration ELSE 0 END) TotalLoadTime,
SUM(CASE DSD.Status WHEN 'Loading' THEN 1 ELSE 0 END) TotalLoadCount
FROM DepotSessions DS
INNER JOIN DepotSessionDetails DSD on DS.ID = DSD.DepotSessionID
GROUP BY TruckID, date;
fiddle
divided by the number of DepotSessions rows for that Date and TruckID.
Above line is not clear .
you can try this way,
select
*, TotalDepotTime * TotalLoadCount
from
(SELECT
DS.Date, DS.TruckID, MIN(DS.StartTime), MAX(DS.EndTime),
SUM(DS.EndTime-DS.StartTime) TotalDepotTime,
SUM(CASE DSD.Status WHEN 'Loading' THEN DSD.Duration ELSE 0 END) TotalLoadTime,
COUNT(CASE DSD.Status WHEN 'Loading' THEN 1 ELSE 0 END) TotalLoadCount
FROM
DepotSessions DS
INNER JOIN
DepotSessionDetails DSD ON DS.ID = DSD.DepotSessionID
GROUP BY Date, TruckID) tbl
Related
I have 2 tables, Tbl1 and Tbl2 :
Tbl1:
ID Col1 Col2 Sold Total
1 AA 0 100
1 BB CC 2 200
1 DD EE 3 300
2 FF GG 1 100
Tbl2:
ID Sold Total TotalPerPax
I need to calculate the TotalPerPax in Tbl2 depending on the ID But the calculation of the TotalPerPax is like this. Example:
ID = 1
Sold: 0 + 2 + 3 = 5
Total = 100 + 200 + 300 = 600
TotalPerPax = (Total minus the Total of the row that has 0 sold / Sold )
(600 -100 ) / 5 = 500
The output should look like this
Tbl2:
ID Sold Total TotalPerPax
1 5 600 100 -- (500 Total / 5 Sold)
2 1 100 100
So far I have this:
When executing it throws an error "Divide by zero error encountered" thus I can't compute the totalPerPax correctly. Can anyone can help me to with this? Thanks
SELECT ID,
Col1
Col2,
Sold,
Total,
SUM(COALESCE(Total, 0))/SUM(COALESCE(Sold, 0)) As TotalPerPax
FROM Tbl1 t1
Where ID = 1
GROUP BY ID, Col1, Col2,Sold, Total
Sample sql fiddle: http://sqlfiddle.com/#!18/09971/2
aI would phrase this as:
SELECT
ID,
SUM(Sold) AS Sold,
SUM(Total) AS Total,
CASE WHEN SUM(Sold) > 0
THEN SUM(CASE WHEN Sold > 0 THEN Total ELSE 0 END) /
SUM(CASE WHEN Sold > 0 THEN Sold ELSE 0 END)
ELSE 0 END AS TotalPerPax
FROM TBl1
GROUP BY ID;
Demo
The CASE expression for TotalPerPax uses logic which does not include any total or sold amount when the latter happens to be zero. As a note, for any ID which only might have zero sold amounts, TotalPerPax would be reported as zero.
I have data like this: (table name: Activities)
ActivityId CreatedOn TypeId
1 2017-01-01 1
1 2017-01-02 1
1 2017-01-02 2
2 2017-01-01 3
Where Type is a lookup value: (table name: Types)
TypeId Name
1 Question
2 Answer
3 Comment
Basically it's an activity history table.
I want to turn the above tables into a grouped sum row for types, for each ActivityId, like this:
ActivityId QuestionCount AnswerCount CommentCount
1 2 1 0
2 0 0 1
I know the answer is probably pretty simple, but it's eluding me for some reason.
Any help? Thanks in advance.
A simple join and conditional aggregation should do the trick (I suspect you were over-thinking it)
Select ActivityID
,QuestionCount = sum(case when Name='Question' then 1 else 0 end)
,AnswerCount = sum(case when Name='Answer' then 1 else 0 end)
,CommentCount = sum(case when Name='Comment' then 1 else 0 end)
From Activities A
Join Types B on A.TypeId=B.TypeId
Group By ActivityId
Returns
ActivityID QuestionCount AnswerCount CommentCount
1 2 1 0
2 0 0 1
You could also do it without the Join... Just less readable
Select ActivityID
,QuestionCount = sum(case when TypeId=1 then 1 else 0 end)
,AnswerCount = sum(case when TypeId=2 then 1 else 0 end)
,CommentCount = sum(case when TypeId=3 then 1 else 0 end)
From #Activities A
Group By ActivityId
You could also try a PIVOT
Select ActivityID
,[1] as QuestionCount
,[2] as AnswerCount
,[3] as CommentCount
From (Select ActivityId,TypeID,1 as Cnt From #Activities) A
Pivot (count(Cnt) For TypeId in ([1],[2],[3]) ) p
I have a table like this
MonthYear JobType JobID
01-2014 FullTime 1
01-2014 PartTime 2
02-2014 FullTime 3
03-2014 FullTime 4
04-2014 PartTime 5
04-2014 PartTime 6
04-2014 FullTime 7
I want to select the count of each job type grouped by MonthYear as follows.
MonthYear FullTime PartTime
01-2014 1 1
02-2014 1 0
03-2014 1 0
04-2014 1 2
Can anyone suggest how to achieve this?
Thanks.
SELECT MonthYear,
SUM(CASE WHEN JobType='FullTime' THEN 1 ELSE 0 END) as FullTime ,
SUM(CASE WHEN JobType='PartTime' THEN 1 ELSE 0 END) as PartTime
FROM t
GROUP BY MonthYear
Pivot solution:
SELECT
[MonthYear],
[FullTime],
[PartTime]
FROM
(values
('01-2014', 'FullTime',1),
('01-2014', 'PartTime',2),
('02-2014', 'FullTime',3),
('03-2014', 'FullTime',4),
('04-2014', 'PartTime',5),
('04-2014', 'PartTime',6),
('04-2014', 'FullTime',7)) x(MonthYear, JobType, JobID)
PIVOT (count(JobType)
for JobType
in([FullTime],[PartTime])
)as p
ORDER BY MonthYear
I have a table as below .
Id Product1 Product2 Product3
1 1 null null
2 1 2 null
3 3 1 null
4 2 3 1
Now I would like to write a query to count the entries with Product 1.
In the above case it is 2 for Product1 , 1 for Product2 and 1 for Product 3
I came up with a query something like this.
select
Count(Product1) +
Count(Product2) +
Count(Product3)
from
Table
where Product1 = 1
But it gives me an inaccurate result.
Is there a way I can get the number of occurances for each product ?
Group By
Desired output would be something like this :
ProductID Product1Count Product2Count Product3Count
1 2 1 1
2 1 1 0
3 1 1 0
select Count(CASE WHEN Product1 = 1 THEN 1 END) +
Count(CASE WHEN Product2 = 1 THEN 1 END) +
Count(CASE WHEN Product3 = 1 THEN 1 END)
from Table1
where 1 IN (Product1, Product2, Product3)
SQLFIddle Demo
The reason for adding this line: where 1 IN (Product1, Product2, Product3) is to count only on the affected rows, thus making it more faster than running through all records.
Something like this would work:
SELECT
SUM(CASE WHEN Product1 = 1 THEN 1 ELSE 0 END)
+ SUM(CASE WHEN Product2 = 1 THEN 1 ELSE 0 END)
+ SUM(CASE WHEN Product3 = 1 THEN 1 ELSE 0 END)
FROM Table
I have a query in MS SQL Server asking for name and some date-related information, depending on two dates, a start- and an enddate.
The problem is, I´m not always getting the same performance. Whenever I request something between the dates;
2010-07-01 00:00:00.000 and
2011-07-21 23:59:59.999
the performance is excellent. I get my result within mseconds. When I request something between these dates, for example,
2011-07-01 00:00:00.000 and
2011-07-21 23:59:59.999
the performance is.. less than good, taking between 20-28 seconds for each query. Do note how the dates giving good performance is more than a year between, while the latter is 20 days.
Is there any particular reason (maybe related to how DATETIME work) for this?
EDIT: The query,
SELECT ENAME,
SUM(CASE DATE WHEN 0 THEN 1 ELSE 0 END) AS U2,
SUM(CASE DATE WHEN 1 THEN 1 ELSE 0 END) AS B_2_4,
SUM(CASE DATE WHEN 2 THEN 1 ELSE 0 END) AS B_4_8,
SUM(CASE DATE WHEN 3 THEN 1 ELSE 0 END) AS B_8_16,
SUM(CASE DATE WHEN 4 THEN 1 ELSE 0 END) AS B_16_24,
SUM(CASE DATE WHEN 5 THEN 1 ELSE 0 END) AS B_24_48,
SUM(CASE DATE WHEN 6 THEN 1 ELSE 0 END) AS O_48,
SUM(CASE DATE WHEN 7 THEN 1 ELSE 0 END) AS status,
AVG(AVG) AS AVG,
SUM(DATE) AS TOTAL
FROM
(SELECT ENAME,
(CASE
WHEN status = 'Öppet' THEN 7
WHEN DATE < 48 THEN
(CASE WHEN DATE BETWEEN 0 AND 2 THEN 0
WHEN DATE BETWEEN 2 AND 4 THEN 1
WHEN DATE BETWEEN 4 AND 8 THEN 2
WHEN DATE BETWEEN 8 AND 16 THEN 3
WHEN DATE BETWEEN 16 AND 24 THEN 4
WHEN DATE BETWEEN 24 AND 48 THEN 5
ELSE - 1 END)
ELSE 6 END) AS DATE,
DATE AS AVG
FROM
(SELECT DATEDIFF(HOUR, cases.date, status.date) AS DATE,
extern.name AS ENAME,
status.status
FROM
cases INNER JOIN
status ON cases.id = status.caseid
AND status.date =
(SELECT MAX(date) AS Expr1
FROM status AS status_1
WHERE (caseid = cases.id)
GROUP BY caseid) INNER JOIN
extern ON cases.owner = extern.id
WHERE (cases.org = 'Expert')
AND (cases.date BETWEEN '2009-01-15 09:48:25.633'
AND '2011-07-21 09:48:25.633'))
AS derivedtbl_1)
AS derivedtbl_2
GROUP BY ENAME
ORDER BY ENAME
(parts of) The tables:
Extern
-ID (->cases.owner)
-name
Cases
-Owner (->Extern.id)
-id (->status.caseid)
-date (case created at this date)
Status
-caseid (->cases.id)
-Status
-Date (can be multiple, MAX(status.date) gives us date when
status was last changed)
I would have thought a statistics issue.
When you are only selecting the most recent dates these may be unrepresented in the statistics yet as the threshold has not yet been reached that would trigger auto updating.
See this blog post for an example.