2015-03-21 5 views
0

я следующие данные в моей webinar_timing таблицы в базе данных MySQLMysql - SQL-запрос, чтобы получить следующий класс на основе даты

start_time и end_time имеют тип DateTime

 

    id | webinar_id | start_time   | end_time 
------------------------------------------------------------------- 
    1 |  5  | 3/18/2015 6:00:00 PM | 3/18/2015 7:00:00 PM 
    2 |  5  | 3/19/2015 6:00:00 PM | 3/19/2015 7:00:00 PM 
    3 |  5  | 3/20/2015 6:00:00 PM | 3/20/2015 7:00:00 PM 
    4 |  5  | 3/21/2015 6:00:00 PM | 3/21/2015 7:00:00 PM 
    5 |  5  | 3/22/2015 6:00:00 PM | 3/22/2015 7:00:00 PM 
    6 | 11  | 3/20/2015 8:00:00 PM | 3/20/2015 9:00:00 PM 
    7 | 11  | 3/21/2015 8:00:00 PM | 3/21/2015 9:00:00 PM 
    8 | 11  | 3/22/2015 8:00:00 PM | 3/22/2015 9:00:00 PM 
    9 | 22  | 3/25/2015 8:00:00 PM | 3/25/2015 9:00:00 PM 
    10 | 22  | 3/27/2015 8:00:00 PM | 3/27/2015 9:00:00 PM 
    11 | 22  | 3/29/2015 8:00:00 PM | 3/27/2015 9:00:00 PM 

В принципе, для каждого вебинара, Я хочу, чтобы общее число вхождений и числа классов завершенных или оставшиеся и СЛЕДУЮЩИЙ предстоящего класс

Egs: Когда я запускаю этот запрос говорят на 3/21/2015 в 4:00 PM - это результат я ожидал

 
webinar_id | total  | Classes Completed | Next Class 
---------------------------------------------------------- 
    5  | 5  | 3     | 3/21/2015 6:00:00 PM 
    11  | 3  | 1     | 3/21/2015 8:00:00 PM 
    22  | 3  | 0     | 3/25/2015 8:00:00 PM 

ИЛИ

 
webinar_id | total  | Classes Remaining | Next Class 
---------------------------------------------------------- 
    5  | 5  | 2     | 3/21/2015 6:00:00 PM 
    11  | 3  | 2     | 3/21/2015 8:00:00 PM 
    22  | 3  | 3     | 3/25/2015 8:00:00 PM 

Основываясь на предыдущий вопрос - собрата SO Петр помогал со следующим

select webinar_id, count(*) AS total, 
SUM(IF(end_time<NOW(), 1, 0)) AS completed, 
SUM(IF(start_time>=NOW(), 1, 0)) AS remaining 
from webinar_times 
group by webinar_id; 

SQL Скрипки http://sqlfiddle.com/#!9/c4e71/1

Любая помощь будет оценена Спасибо аванс

+0

Можете ли вы предоставить образцы данных в качестве операторов вставки или создать sqlfiddle? – Lennart

+0

Привет Леннарт - я добавил sqlfiddle - в основном нужно добавить следующую дату класса к результату - Спасибо – Gublooo

ответ

1

Что-то вроде:

select webinar_id 
    , count(*) AS total 
    , count(case when end_time<NOW() then 1 end) as completed 
    , (select count(1) 
     from webinar_times y 
     where x.webinar_id = y.webinar_id 
      and y.start_time > NOW()) as remaining 
    , min(case when x.start_time > NOW() then x.start_time end) as next_class 
from webinar_times x 
group by webinar_id; 

должен сделать

EDIT: понял, что к югу от выбора является ненужной:

select webinar_id 
    , count(*) AS total 
    , count(case when end_time<NOW() then 1 end) as completed 
    , count(case when start_time>NOW() then 1 end) as remaining 
    , min(case when x.start_time > NOW() then x.start_time end) as next_class  
from webinar_times x 
group by webinar_id; 
+0

Привет Леннарт - это не дает следующий следующий класс в результате - спасибо – Gublooo

+0

Прости, пропустил тот. Я обновил ответ – Lennart

+0

Спасибо Lennart - позвольте мне проверить производительность этого запроса – Gublooo

0

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

SELECT * FROM (
    SELECT webinar_id, COUNT(*) total 
    FROM  webinar_times 
    GROUP BY webinar_id 
) totals NATURAL LEFT JOIN (
    SELECT webinar_id, COUNT(*) remaining, MIN(start_time) next 
    FROM  webinar_times 
    WHERE start_time > NOW() 
    GROUP BY webinar_id 
) future 

Посмотри по sqlfiddle:

 
+------------+-------+-----------+-------------------------+ 
| webinar_id | total | remaining |     next | 
+------------+-------+-----------+-------------------------+ 
|   6 |  5 |   1 | March, 22 2015 06:00:00 | 
|   11 |  3 |   1 | March, 22 2015 07:00:00 | 
|   22 |  3 |   3 | March, 25 2015 07:00:00 | 
+------------+-------+-----------+-------------------------+ 

Составной индекс, определенный над (webinar_id, start_time) выиграет от этого запроса и избежит полного сканирования таблицы, который в противном случае потребовал бы описанный в вашем вопросе подход.

+0

Пойдем - посмотрим на создание составного индекса - В этом запросе - можно также получить завершенные классы вместе с оставшиеся классы – Gublooo

+1

@ Gublooo: Можно просто добавить 'total - оставшиеся AS завершенные' в (внешний)' SELECT' список (или сделать это на уровне доступа к данным). – eggyal

0

Рассмотрим следующий пример, и это даст вам то, что вам необходимо

mysql> create table test (id int, webinar_id int, start_time datetime); 
Query OK, 0 rows affected (0.16 sec) 

mysql> insert into test values (1,5,'2015-03-18 18:00:00'), 
    (2,5,'2015-03-19 18:00:00'), 
    (3,5,'2015-03-20 18:00:00'), 
    (4,5,'2015-03-21 18:00:00'), 
    (5,5,'2015-03-21 18:00:00'), 
    (6,11,'2015-03-20 20:00:00'), 
    (7,11,'2015-03-21 20:00:00'), 
    (8,11,'2015-03-22 20:00:00'), 
    (9,22,'2015-03-25 20:00:00'), 
    (10,22,'2015-03-27 20:00:00'), 
    (11,22,'2015-03-29 20:00:00'); 
Query OK, 11 rows affected (0.05 sec) 

Records: 11 Duplicates: 0 Warnings: 0 

mysql> select * from test ; 
+------+------------+---------------------+ 
| id | webinar_id | start_time   | 
+------+------------+---------------------+ 
| 1 |   5 | 2015-03-18 18:00:00 | 
| 2 |   5 | 2015-03-19 18:00:00 | 
| 3 |   5 | 2015-03-20 18:00:00 | 
| 4 |   5 | 2015-03-21 18:00:00 | 
| 5 |   5 | 2015-03-21 18:00:00 | 
| 6 |   11 | 2015-03-20 20:00:00 | 
| 7 |   11 | 2015-03-21 20:00:00 | 
| 8 |   11 | 2015-03-22 20:00:00 | 
| 9 |   22 | 2015-03-25 20:00:00 | 
| 10 |   22 | 2015-03-27 20:00:00 | 
| 11 |   22 | 2015-03-29 20:00:00 | 
+------+------------+---------------------+ 
11 rows in set (0.00 sec) 

select 
t.webinar_id, 
count(*) as total, 
sum(case when t.start_time < now() then 1 else 0 end) as completed , 
sum(case when t.start_time > now() then 1 else 0 end) as remaining, 
t1.next_date from test t 
join ( 
    select 
    webinar_id, 
    min(start_time) as next_date 
    from test where start_time > now() 
    group by webinar_id 
)t1 on t.webinar_id= t1.webinar_id 
group by t.webinar_id; 

+------------+-------+-----------+-----------+---------------------+ 
| webinar_id | total | completed | remaining | next_date   | 
+------------+-------+-----------+-----------+---------------------+ 
|   5 |  5 |   3 |   2 | 2015-03-21 18:00:00 | 
|   11 |  3 |   1 |   2 | 2015-03-21 20:00:00 | 
|   22 |  3 |   0 |   3 | 2015-03-25 20:00:00 | 
+------------+-------+-----------+-----------+---------------------+ 
3 rows in set (0.00 sec) 
+0

Возможно, вы хотите, чтобы это было внешнее соединение, так что любые веб-семинары, для которых нет оставшихся классов, не полностью удаляются из набора результатов. – eggyal

+0

Спасибо Abhik - это похоже на подход, предложенный eggyal. Позвольте мне изучить это немного - спасибо большое – Gublooo

+0

. Правильное левое внешнее соединение должно быть необходимо, чем внутреннее соединение, чтобы выполнить это условие. –

Смежные вопросы