Подсчет строк в SQL-выражении с использованием группировки по инкрементальным переменным - PullRequest
0 голосов
/ 10 апреля 2009

Таблица, из которой я пытаюсь получить аналитический результат - это запись голосовых вызовов. Каждый вызов (одна строка) имеет длительность в секундах (только значение типа int, а не datetime). Я пытаюсь получить количество записей, сгруппированных по интервалам в 15 секунд, например:

+-------------------+
|Period | Count     |
+-------------------+
| 0-15  | 213421    |
|15-30  | 231123    |
|30-45  | 1234      |
+-------------------+

Начало периода 0, конец 86400.

Я пробовал некоторые комбинации с установкой переменных для начала и конца и затем увеличивал их на 15, но я не очень успешен, и я не могу понять, что происходит не так.

Пожалуйста, помогите. Спасибо!

Ответы [ 4 ]

3 голосов
/ 10 апреля 2009

Следующий запрос соответствует вашим потребностям:

SELECT
  (duration - duration % 15),
  COUNT(*)
FROM
  call
GROUP BY
  (duration - duration % 15)
ORDER BY
  1;

Вы также можете добавить некоторое форматирование строки, если вам нужен вывод в точности так, как вы его описали:

SELECT
  (duration - duration % 15)::text || '-' || (duration - duration % 15 + 15)::text,
  COUNT(*)
FROM
  call
GROUP BY
  (duration - duration % 15)
ORDER BY
  1;
2 голосов
/ 10 апреля 2009

В MySQL:

SELECT  CONCAT(span * 15, '-', span * 15 + 15), COUNT(*) AS cnt
FROM    (
        SELECT  v.*, FLOOR(period / 15) AS span
        FROM    voice_calls v
        ) q
GROUP BY
        span

UPDATE:

Решение, которое вы разместили, будет работать, при условии, что всегда будет более 5760 строк.

Но вам лучше создать фиктивный набор строк из 5760 строк и использовать его в OUTER JOIN:

CREATE TABLE spans (span INT NOT NULL PRIMARY KEY);

INSERT
INTO    spans
VALUES  (0),
        (1),
        ...
        (5759)

SELECT  span * 15, COUNT(*)
FROM    spans
LEFT JOIN
        calls
ON      call.duration >= span * 15
        AND call.duration < span * 15 + 15
GROUP BY
        span

Это будет более эффективно и разумно, поскольку не может ни потерять (если меньше 5760 строк в calls), ни занять много времени, если там миллионы строк.

0 голосов
/ 10 апреля 2009

Наконец-то это сработало:

SET @a:=-15, @b:=0;
SELECT  t.start_time, t.end_time, count(c.duration)
FROM    calls c,
        (
        SELECT  (@a:=@a+15) as start_time, (@b:=@b+15) as end_time 
        FROM    `calls`  
        GROUP BY
                 cdr_id
        ) as t
WHERE   c.duration BETWEEN t.start_time and t.end_time
GROUP BY
        t.start_time, t.end_time
0 голосов
/ 10 апреля 2009

Я думаю, что такой запрос должен работать; Вы должны будете самостоятельно отобразить результаты на дисплее (например, этот запрос получает результаты по горизонтали, вам придется отображать их по вертикали):

SELECT
    SUM(CASE WHEN CallLength BETWEEN 0 AND 15 THEN CallLength ELSE 0 END) AS ZeroToFifteen,
    SUM(CASE WHEN CallLength BETWEEN 16 AND 30 THEN CallLength ELSE 0 END) AS FifteenToThirty
FROM CallTable

Но после повторного прочтения вопроса вопрос о том, чтобы указывать регистр до 86400, вероятно, не может быть и речи ... О, хорошо :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...