Domanda

Here is my query:

SELECT 
   dateTime, 
   AVG([timeTaken]) as avgtime, 
   MAX([timeTaken]) as maxtime, 
   COUNT(*) totalcalls
FROM 
   [Logs]
WHERE 
   csUriStem = '/REST/Issues/Issues.svc/' AND 
   [dateTime] > DATEADD(MINUTE, -15, GETUTCDATE()) AND
   (csUserAgent != 'Fiddler' OR csUserAgent IS NULL)

I get this error when executed:

Msg 8120, Level 16, State 1, Line 2
Column 'Logs.dateTime' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

I understand why, but my question is, how do I get the associated DateTime to the corresponding [MAX([timeTaken]) as maxtime]?

È stato utile?

Soluzione

Okay, so aggregate functions like AVG, MAX, and COUNT will require some sort of GROUP BY if there are other fields in the SELECT list. This is how they know what subset to operate on. So what you would need to do, to get this to run, is something like this:

SELECT dateTime,
    AVG([timeTaken]) as avgtime,
    MAX([timeTaken]) as maxtime,
    COUNT(*) totalcalls
FROM [Logs]
WHERE 
    csUriStem = '/REST/Issues/Issues.svc/' AND 
    [dateTime] > DATEADD(MINUTE, -15, GETUTCDATE()) AND
    (csUserAgent != 'Fiddler' OR csUserAgent IS NULL)
GROUP BY dateTime

However, that may, or may not, be what you want. This is going to perform the AVG, MAX, and COUNT over every grouping of dateTime.

However, this grouping of dateTime is probably illogical; you probably want something like this:

SELECT CONVERT(VARCHAR(8), dateTime, 101) AS groupDate,
    AVG([timeTaken]) as avgtime,
    MAX([timeTaken]) as maxtime,
    COUNT(*) totalcalls
FROM [Logs]
WHERE 
    csUriStem = '/REST/Issues/Issues.svc/' AND 
    [dateTime] > DATEADD(MINUTE, -15, GETUTCDATE()) AND
    (csUserAgent != 'Fiddler' OR csUserAgent IS NULL)
GROUP BY CONVERT(VARCHAR(8), dateTime, 101)

That will format that grouping date by mm/dd/yy.

To further consider what's actually going on with aggregate functions, if you didn't have any additional fields:

SELECT AVG([timeTaken]) as avgtime,
    MAX([timeTaken]) as maxtime,
    COUNT(*) totalcalls
FROM [Logs]
WHERE 
    csUriStem = '/REST/Issues/Issues.svc/' AND 
    [dateTime] > DATEADD(MINUTE, -15, GETUTCDATE()) AND
    (csUserAgent != 'Fiddler' OR csUserAgent IS NULL)

it still operates over a group. That group just happens to be the entire result set.

Altri suggerimenti

You need to include it in a group by clause

Something like this.

SELECT 
    dateTime, 
    AVG([timeTaken]) as avgtime, 
    MAX([timeTaken]) as maxtime, 
    COUNT(*) totalcalls
  FROM 
    [Logs]
  WHERE
    csUriStem = '/REST/Issues/Issues.svc/' AND 
    [dateTime] > DATEADD(MINUTE, -15, GETUTCDATE()) AND
    (csUserAgent != 'Fiddler' OR csUserAgent IS NULL)
  GROUP BY
    dateTime;

Note if you want information on the average and max seperately then you need to split up the query into two separate queries. Then merge them after.

You need to include the dateTime column in the group by OR choose avg / max / min depending on your requirements.

 SELECT dateTime, AVG([timeTaken]) as avgtime, MAX([timeTaken]) as maxtime, COUNT(*) totalcalls
      FROM [Logs]
      WHERE 
        csUriStem = '/REST/Issues/Issues.svc/' AND 
        [dateTime] > DATEADD(MINUTE, -15, GETUTCDATE()) AND
        (csUserAgent != 'Fiddler' OR csUserAgent IS NULL)
      GROUP BY dateTime

If you only want one row and you want it for the maximum value of DateTime, then you can do this using aggregation, order by, and top:

SELECT TOP 1 dateTime, AVG([timeTaken]) as avgtime, 
       MAX([timeTaken]) as maxtime, COUNT(*) totalcalls
FROM [Logs]
WHERE csUriStem = '/REST/Issues/Issues.svc/' AND 
      [dateTime] > DATEADD(MINUTE, -15, GETUTCDATE()) AND
      (csUserAgent != 'Fiddler' OR csUserAgent IS NULL)
GROUP BY dateTime
order by dateTime desc;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top