简体   繁体   中英

SQL calculate individual Average based on multiple conditions

I have the following table:

+-----------+----------+-------------+----------------+---------------+
| FirstName | LastName | SessionDate |  SessionTitle  | TotalDistance |
+-----------+----------+-------------+----------------+---------------+
| Player    | Striker  |  05.08.2020 | Entire Session |          10.0 |
| Player    | Striker  |  05.08.2020 | 1v1            |           5.0 |
| Player    | Striker  |  06.08.2020 | Entire Session |          12.0 |
| Coach     | Defender |  06.08.2020 | Entire Session |           7.0 |
+-----------+----------+-------------+----------------+---------------+

What I need to do is to calculate the average for totalDistance, for each player individually. The average should only be calculated with values, where the SessionTitle is 'EntireSession' and only for the last 50 days including the date of the row for each row. So the expected result would look like this:

+-----------+----------+-------------+----------------+---------------+---------+
| FirstName | LastName | SessionDate |  SessionTitle  | TotalDistance | average |
+-----------+----------+-------------+----------------+---------------+---------+
| Player    | Striker  |  05.08.2020 | Entire Session |          10.0 |    10.0 |
| Player    | Striker  |  05.08.2020 | 1v1            |           5.0 |    10.0 |
| Player    | Striker  |  06.08.2020 | Entire Session |          12.0 |    11.0 |
| Coach     | Defender |  06.08.2020 | Entire Session |           7.0 |     7.0 |
+-----------+----------+-------------+----------------+---------------+---------+

I tried something like this, but it is awfully slow, when more rows are added:

SELECT t1.FirstName, 
t1.LastName, 
t1.SessionDate, 
t1.SessionTitle, 
t1.TotalDistance, 
(SELECT (AVG(t2.TotalDistance) FROM myTable t2 WHERE t1.FirstName = t2.FirstName AND t1.LastName = t2.LastName AND t2.SessionTitle = 'EntireSession' AND t2.SessionDate <= DATEADD(DAY,50,t1.SessionDate)) as average
FROM myTable t1

It is running on a Azure SQL-Server How would be the fastest way to get this done in a select statement?

Thanks in advance!

This is your query:

SELECT t1.FirstName, t1.LastName, t1.SessionDate, t1.SessionTitle, 
       t1.TotalDistance, 
       (SELECT AVG(t2.TotalDistance)
        FROM myTable t2
        WHERE t1.FirstName = t2.FirstName AND
              t1.LastName = t2.LastName AND
              t2.SessionTitle = 'EntireSession' AND
              t2.SessionDate <= DATEADD(DAY,50,t1.SessionDate)
       ) as average
FROM myTable t1;

First, you can try adding an index on (FirstName, LastName, SessionDate, SessionTitle, TotalDistance) .

Second, this looks a bit like like a window function to me. If you have data on every day, then you can use:

select t.*,
       avg(case when SessionTitle = 'EntireSession' then TotalDistance end) over (
           (partition by FirstName, LastName
            order by SessionDate
            rows between unbounded preceding and 50 following
           )
from myTable t;

You can simply achieve this by

SELECT FirstName, LastName, avg([TotalDistance]) 
FROM myTable
WHERE SessionDate>= DATEADD(Day, -50, getdate())
AND SessionTitle = 'EntireSession'
GROUP BY FirstName, Last Name

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM