Reputation: 11712
I have a simple data model for users and their requests:
User
- id,
- name
Request
- id,
- createdAt,
- completedAt,
- status
- userId (FK to user)
I'm trying to run a query which collects some stats for every user. The issue is that I have to run the same subquery to fetch user requests for every parameter I select. As instead, I want to run it once and then calculate some stats over it.
select
u.id as UserId,
(select count(*)
from Requests r
where userId = u.id
and timestamp > @dateFrom) as Total,
(select count(*)
from Requests r
where userId = u.id
and timestamp > @dateFrom
and status = N'Completed') as Completed,
(select status
from Requests r
where userId = u.id
and timestamp > @dateFrom
and status != N'Completed') as ActiveStatus,
(select datediff(second, createdAt, completedAt)
from Requests r
where userId = u.id
and timestamp > @dateFrom
and status == N'Completed') as AvgProcessingTime
from User u
Obviously, this query is very slow and I need to optimize it. I tried join, apply, rank, nothing worked out well for me (read as I wasn't able to complete the query for all required stats).
What is the best approach here from the performance stand point?
Upvotes: 0
Views: 97
Reputation: 883
I'm not sure about this query cause I haven't run it on my machine, but you can give it a try and make some changes accordingly if needed --
SELECT U.ID AS USERID
,COUNT(R.ID) AS TOTAL
,SUM(CASE
WHEN R.[STATUS] = N'COMPLETED'
THEN 1
END) AS [COMPLETED]
,CASE
WHEN R.[STATUS] <> N'COMPLETED'
THEN [STATUS]
END AS [ACTIVE STATUS]
,CASE
WHEN R.[STATUS] = N'COMPLETED'
THEN DATEDIFF(SECOND, CREATEDAT, COMPLETEDAT)
END AS [AVG PROCESSING TIME]
FROM USERS U
LEFT JOIN REQUESTS R ON U.ID = R.USERID
WHERE TIMESTAMP > @DATEFROM
Upvotes: 1
Reputation: 4824
try this using Left Join and aggregation
There could be a couple of issues here but let me know how you go.
select
u.id as UserId
,count(r.UserId) [Total]
,sum(iif(r.status = N'Completed',1,0)) [Completed]
,sum(iif(r.status <> N'Completed',1,0)) [ActiveStatus]
,avg(iif(r.status = N'Completed', datediff(second, createdAt, completedAt),0)) [AvgProcessingTime]
from User u
left join Request R
where timestamp > @datefrom
and r.userId = u.id
group by
u.id
Upvotes: 1