Несколько вычисляемых значений в одном операторе SQL

У меня проблема с программой, которую я пытаюсь завершить. У меня есть таблица, в которой хранятся три отметки времени. Он используется для составления статистики запросов и ответов. Первая метка времени предназначена для даты и времени запроса (Date_Sent), две другие - это первый раз, когда один из наших экспертов отвечает на запрос (FirstResponse) и когда этот запрос был удовлетворен (LastResponse). Я должен создать график на основе следующих критериев:

  1. Общее количество запросов в месяц
  2. Количество запросов, на которые ответили менее чем за два часа.
  3. Количество запросов, на которые ответили менее 24 часов, но более двух
  4. Количество запросов, на которые ответили менее 48 часов, но более 24
  5. Количество запросов, на которые ответили менее 72 часов, но более 48
  6. Количество запросов, на которые ответили менее 96 часов, но более 72

Я могу выполнить первое требование:

SELECT Count(Date_Sent) AS TotalQueries, 
       SUBSTRING(CONVERT(VARCHAR(11), Date_Sent, 113), 4, 8) AS Month, 
       RIGHT(CONVERT(VARCHAR(7), Date_Sent, 120), 2) AS Month_Order 
FROM AskAO.dbo.AskAO_Stats 
WHERE Date_Sent BETWEEN '6/1/2012' AND '6/30/2013' AND 
      FirstResponse != '' AND 
      LastResponse != '' AND 
      FirstResponse < LastResponse   
GROUP BY SUBSTRING(CONVERT(VARCHAR(11), Date_Sent, 113), 4, 8), 
         CONVERT(VARCHAR(7), Date_Sent, 120) 
ORDER BY SUBSTRING(CONVERT(VARCHAR(11), Date_Sent, 113), 4, 8)

Я могу получить этот образец результата:

TotalQueries     Month   Month_Order
    655        Jun 2013      06
    289        May 2013      05

Однако я не знаю, как получить другие :( Я знаю, что могу вычислить значения с помощью DateDiff, но мне понадобится количество запросов, соответствующих этим конкретным критериям, в месяц. Мне понадобится это:

 TotalQueries   2Hrs  24Hrs  48Hrs  72Hrs  96Hrs  Month     Month_Order
     655        300    190    80     55     30    Jun 2013      06
     289        180     50    30     15     14    May 2013      05

Я не знаком со сложным SQL, поэтому не уверен, выполнимо это или нет.


person Poch    schedule 04.07.2013    source источник
comment
Как вы определяете ответили: время между последним ответом и первым ответом или между датой отправки и первым ответом?   -  person Stas Yarkin    schedule 04.07.2013
comment
Есть ли причина, по которой вы пытаетесь сделать все это на SQL? Можете ли вы вернуть набор рекордов и нарезать / нарезать с помощью кода?   -  person David    schedule 04.07.2013
comment
@StasYarkin Спасибо за ответ :) Время ответа находится между датой отправки и первым ответом :) В основном, я вычисляю, насколько быстро наши эксперты отвечают на отдельные запросы.   -  person Poch    schedule 04.07.2013
comment
@David Мы используем веб-приложение, которое автоматически создает диаграмму (на основе xml) из операторов SQL. Я посмотрю, смогу ли я нарезать / нарезать кубиками с помощью кода, если это будет более легкий путь :)   -  person Poch    schedule 04.07.2013


Ответы (2)


попробуйте что-нибудь вроде этого

SELECT Count(Date_Sent) AS TotalQueries, 
    SUBSTRING(CONVERT(VARCHAR(11), Date_Sent, 113), 4, 8) AS Month, 
    RIGHT(CONVERT(VARCHAR(7), Date_Sent, 120), 2) AS Month_Order ,
    SUM(CASE WHEN DATEDIFF(HOUR, FirstResponse, LastResponse) < 2 THEN 1 ELSE 0 END) AS LessThan2Hours,
    SUM(CASE WHEN DATEDIFF(HOUR, FirstResponse, LastResponse) between 2 AND 24 THEN 1 ELSE 0 END) AS LessThan24Hours,
    SUM(CASE WHEN DATEDIFF(HOUR, FirstResponse, LastResponse) between 25 AND 48 THEN 1 ELSE 0 END) AS LessThan24Hours,
    SUM(CASE WHEN DATEDIFF(HOUR, FirstResponse, LastResponse) between 25 AND 48 THEN 1 ELSE 0 END) AS LessThan48Hours,
    SUM(CASE WHEN DATEDIFF(HOUR, FirstResponse, LastResponse) between 49 AND 72 THEN 1 ELSE 0 END) AS LessThan72Hours,
    SUM(CASE WHEN DATEDIFF(HOUR, FirstResponse, LastResponse) between 73 AND 96 THEN 1 ELSE 0 END) AS LessThan96Hours

FROM AskAO.dbo.AskAO_Stats 
WHERE Date_Sent BETWEEN '6/1/2012' AND '6/30/2013' AND FirstResponse != '' AND LastResponse != '' AND FirstResponse < LastResponse   
GROUP BY SUBSTRING(CONVERT(VARCHAR(11), Date_Sent, 113), 4, 8), CONVERT(VARCHAR(7), Date_Sent, 120) 
ORDER BY SUBSTRING(CONVERT(VARCHAR(11), Date_Sent, 113), 4, 8)
person Luis LL    schedule 04.07.2013
comment
Обратите внимание, что dateiff работает с пересеченными границами периодов времени, а не с точными различиями в единицах измерения, поэтому dateiff в часах между 01:59:59 и 03:00:00 вернет 2, несмотря на то, что между два раза. Использование dateiff в секундах (и умножение диапазонов значений на 3600) должно быть более точным. - person ; 04.07.2013
comment
Ребята, огромное вам спасибо за это !!!!! Мне удалось создать таблицу с помощью кодов, которые вы дали! :) Спасибо Спасибо спасибо!!!! :) - person Poch; 04.07.2013
comment
@MarkBannister Нужно ли мне сначала преобразовать столбцы в секунды, прежде чем использовать dateiff? - person Poch; 04.07.2013
comment
@Poch: Нет, просто вычислите датированное значение за секунды - вот так: ...SUM(CASE WHEN DATEDIFF(SECOND, FirstResponse, LastResponse) < 7200 THEN 1 ELSE 0 END) AS LessThan2Hours,... - person ; 04.07.2013
comment
(В моем первом комментарии должен быть указан один час и одна секунда - ох!) - person ; 04.07.2013

Дело в том, что COUNT() подсчитывает только значения, которые не равны нулю. Таким образом, вы можете написать некоторое выражение в COUNT(...) в соответствии с вашей логикой таким образом, чтобы оно было равно нулю, когда вы не хотите суммировать строку, и не нулю в противном случае. Например, чтобы подсчитать количество ответов менее чем за два часа, вы можете написать:

COUNT(CASE WHEN DATEDIFF(HOUR, Date_Sent, FirstResponse) < 2 THEN Date_Sent ELSE NULL END) AS [2Hrs]

Вы можете проделать то же самое со всеми остальными случаями.

person Stas Yarkin    schedule 04.07.2013