Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Найти дырки в таблице
 
 автор: Eugene77   (17.06.2012 в 11:45)   письмо автору
 
 

Таблица имеет уникальный ключ, состоящий из двух колонок:
1) дата и
2) время суток.

Большей частью, расстояние между строками ровно 5 минут,
но изредка встречаются разрывы во времени.

Все эти разрывы необходимо найти

SELECT * FROM nt AS t1 
WHERE NOT EXISTS (
SELECT * FROM  nt AS t2
WHERE 
TIMESTAMP(t1.date, t1.time) = TIMESTAMP(t2.date, t2.time) + INTERVAL 5 MINUTE
)

Так слишком долго работает

  Ответить  
 
 автор: Sfinks   (18.06.2012 в 11:40)   письмо автору
 
   для: Eugene77   (17.06.2012 в 11:45)
 

Ну быстро тут никак не получится.

И вы не уточнили, нужно выводить дату/время перед дыркой или после дырки?
Из вашего запроса я сделал вывод, что после.

Большого объема данных, чтоб проверить скорость нет, так что....
Вот еще два варианта проверьте:
SELECT T1.dt,T1.tm
FROM nt T1 LEFT JOIN nt T2
ON timestamp(T1.dt,T1.tm) = timestamp(T2.dt,T2.tm)+INTERVAL 5 MINUTE
WHERE T2.tm is null
первую строку в выборке нужно отбросить. Впрочем как и в вашем запросе.

И можно еще так извернуться:
SELECT dt, tm FROM(
  SELECT * , @dtm +INTERVAL 5 MINUTE AS nxt, @dtm := timestamp(nt.dt,nt.tm)dtm_val 
  FROM nt
  CROSS JOIN (SELECT @dtm := 0 f1)f1 )T
WHERE nxt<>dtm_val
но сомневаюсь, что будет быстрее.

  Ответить  
 
 автор: Eugene77   (25.06.2012 в 06:37)   письмо автору
 
   для: Sfinks   (18.06.2012 в 11:40)
 

>И вы не уточнили, нужно выводить дату/время перед дыркой или после дырки?
>Из вашего запроса я сделал вывод, что после.

Мне нужно получить последнюю строку перед дыркой и первую перед ней

  Ответить  
 
 автор: Sfinks   (20.06.2012 в 11:19)   письмо автору
 
   для: Eugene77   (17.06.2012 в 11:45)
 

И вот еще, попробуйте такой вариант:
SELECT dt, tm FROM nt 
CROSS JOIN (select 0 x union select 5)x
GROUP BY timestamp(dt,tm)+interval x minute
HAVING max(case x when 5 then 1 end) is null

Вот он, возможно, будет немного быстрее!
P.S. Первую строку также нужно отбросить.

  Ответить  
 
 автор: Eugene77   (25.06.2012 в 06:46)   письмо автору
 
   для: Sfinks   (20.06.2012 в 11:19)
 

Первые два варианта - это то же пересечение таблиц, "только другими словами".

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

  Ответить  
 
 автор: Sfinks   (25.06.2012 в 09:15)   письмо автору
 
   для: Eugene77   (25.06.2012 в 06:46)
 

>Первые два варианта - это то же пересечение таблиц, "только другими словами".
В SQL сравнить разные строки ОДНОЙ таблицы без пересечения НЕ ВОЗМОЖНО.
Так что любое решение будет пересечением.
Вопрос только что с чем пересекать.

Например второе решение - это СОВСЕМ не такое же пересечение, как в первом решении или в Вашем. В нем исходная таблица умножается на таблицу состоящую всего из одной ячейки. И все бы было хорошо и красиво, если бы не необходимость отсева значений по результату выборки. Из-за этого отсева пришлось обернуть результат в еще один подзапрос и на этом весь выигрыш сгорел. И даже стало медленнее из-за того что на выборке из выборки слетели индексы.

>не могли бы вы немного подробней раскрыть как работает этот запрос?

Тут происходит удвоение исходной таблицы за счет умножения ее на таблицу X, которая имеет вид:
-----
| x |
-----
| 0 |
| 5 |
-----

В результате каждая строчка новой таблицы встречается 2 раза в виде:
-------------------
| date | time | x |
-------------------
| dt_1 | tm_1 | 0 |
| dt_1 | tm_1 | 5 |
-------------------

А чтобы понять что с чем группируется и что после группировки отсеивается, выполните промежуточный запрос, чтобы увидеть данные, с которыми работает мускул перед группировкой и отсевом по HAVING:
SELECT *
     , timestamp(dt,tm)+interval x minute gr
     , case x when 5 then 1 end cs
FROM nt   
CROSS JOIN (select 0 x union select 5)x

По другому я объяснить наверно не смогу.

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования