Группировка данных в Sqltable на основе продолжительности - PullRequest
0 голосов
/ 28 апреля 2011

Мне нужно показать чат по сеансам, и сеанс может быть разделен на 30-минутный промежуток между каждым сообщением.

здесь образец таблицы

S.No From To Время сообщения

  1. Джон Майкл, привет, 12:00
  2. Майкл Джон привет да 12: 01
  3. Майкл Джон, ты там 12: 40

здесь первые два сообщения отправляются с интервалом в 1 минуту. но третье сообщение отправляется через 39 минут, поэтому первые два сообщения - это один сеанс, а третье сообщение - это второй сеанс. Как я могу разделить, как это.

Ответы [ 2 ]

2 голосов
/ 28 апреля 2011

Вы также пометили свой вопрос «Oracle», так что вот решение Oracle.В следующем запросе вы увидите выражение с псевдонимом «GRP», которое вы можете использовать для группировки строк, которые принадлежат друг другу:

SQL> select s_no
  2       , s_from
  3       , s_to
  4       , message
  5       , s_time
  6       , case
  7         when nvl(lag(s_time) over (partition by least(s_from,s_to),greatest(s_from,s_to) order by s_time,s_no),s_time)
  8           > s_time - interval '30' minute
  9         then
 10           first_value(s_time) over (partition by least(s_from,s_to),greatest(s_from,s_to) order by s_time,s_no)
 11         else
 12           s_time
 13         end grp
 14    from messages
 15   order by s_no
 16  /

      S_NO S_FROM  S_TO    MESSAGE       S_TIME              GRP
---------- ------- ------- ------------- ------------------- -------------------
         1 John    Michael hello         28-04-2011 12:00:00 28-04-2011 12:00:00
         2 Michael John    hi da         28-04-2011 12:01:00 28-04-2011 12:00:00
         3 Michael John    are you there 28-04-2011 12:40:00 28-04-2011 12:40:00
         4 Michael Alan    hi            28-04-2011 12:15:00 28-04-2011 12:15:00
         5 Alan    Michael bye           28-04-2011 12:18:00 28-04-2011 12:15:00

5 rows selected.

А вот пример того, как вы можете использовать это выражение группировки для создания чата.:

SQL> select min(s_no) s_no_from
  2       , max(s_no) s_no_to
  3       , least(s_from,s_to) participant1
  4       , greatest(s_from,s_to) participant2
  5       , min(s_time) time_from
  6       , max(s_time) time_to
  7    from ( select s_no
  8                , s_from
  9                , s_to
 10                , message
 11                , s_time
 12                , case
 13                  when nvl(lag(s_time) over (partition by least(s_from,s_to),greatest(s_from,s_to) order by s_time,s_no),s_time)
 14                    > s_time - interval '30' minute
 15                  then
 16                    first_value(s_time) over (partition by least(s_from,s_to),greatest(s_from,s_to) order by s_time,s_no)
 17                  else
 18                    s_time
 19                  end grp
 20             from messages
 21         )
 22   group by least(s_from,s_to)
 23       , greatest(s_from,s_to)
 24       , grp
 25   order by min(s_time)
 26  /

 S_NO_FROM    S_NO_TO PARTICI PARTICI TIME_FROM           TIME_TO
---------- ---------- ------- ------- ------------------- -------------------
         1          2 John    Michael 28-04-2011 12:00:00 28-04-2011 12:01:00
         4          5 Alan    Michael 28-04-2011 12:15:00 28-04-2011 12:18:00
         3          3 John    Michael 28-04-2011 12:40:00 28-04-2011 12:40:00

3 rows selected.

С уважением,
Роб.

0 голосов
/ 28 апреля 2011

РЕДАКТИРОВАТЬ

Версия MySQL:

CREATE TABLE messages(
  S_NO INT(11) NOT NULL,
  S_FROM VARCHAR(255) DEFAULT NULL,
  S_TO VARCHAR(255) DEFAULT NULL,
  MESSAGE VARCHAR(255) DEFAULT NULL,
  S_TIME DATETIME DEFAULT NULL,
  PRIMARY KEY (S_NO)
);

INSERT INTO messages VALUES 
  (1, 'John', 'Michael', 'hello', '2011-04-28 12:00:00'),
  (2, 'Michael', 'John', 'hi da', '2011-04-28 12:01:00'),
  (3, 'Michael', 'John', 'are you there', '2011-04-28 12:40:00'),
  (4, 'Michael', 'Alan', 'hi', '2011-04-28 14:15:00'),
  (5, 'Alan', 'Michael', 'bye', '2011-04-28 14:41:00');

SET @group_number = 0;
SET @prev_time = NULL;
SET @temp_time = NULL;
SELECT group_number, s_no, s_from, s_to, message, s_time FROM (
  SELECT
    m.*,
    @temp:=@prev_time,
    @prev_time:=(SELECT MAX(S_TIME) FROM messages WHERE S_TIME < m.S_TIME) prev_time,
    TIMESTAMPDIFF(MINUTE, @prev_time, S_TIME),
    @group_number:=CASE WHEN @prev_time IS NULL THEN 1 WHEN @temp=@prev_time OR TIMESTAMPDIFF(MINUTE, @prev_time, S_TIME) < 30 THEN @group_number ELSE @group_number + 1 END group_number
  FROM messages m
  ORDER BY m.S_TIME) t;

+--------------+------+---------+---------+---------------+---------------------+
| group_number | s_no | s_from  | s_to    | message       | s_time              |
+--------------+------+---------+---------+---------------+---------------------+
|            1 |    1 | John    | Michael | hello         | 2011-04-28 12:00:00 |
|            1 |    2 | Michael | John    | hi da         | 2011-04-28 12:01:00 |
|            2 |    3 | Michael | John    | are you there | 2011-04-28 12:40:00 |
|            3 |    4 | Michael | Alan    | hi            | 2011-04-28 14:15:00 |
|            3 |    5 | Alan    | Michael | bye           | 2011-04-28 14:41:00 |
+--------------+------+---------+---------+---------------+---------------------+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...