python: mysql: вернет 0, если строки не найдены - PullRequest
1 голос
/ 22 января 2010

Структура таблицы - данные представлены за 5 мин. слоты -

data_point | point_date

12 | 00: 00

14 | 00: 05

23 | 00: 10

10 | 00: 15

43 | 00: 25

10 | 00:40

Когда я запускаю запрос, скажем, 30 минут. и если данные присутствуют, я получу 6 строк (по одной строке на каждые 5 минут печати). Простой запрос -

select data_point<br> from some_table<br> where point_date >= start_date<br> AND point_date < end_date<br> order by point_date

Теперь, когда у меня нет записи для определенного временного интервала (например, временной интервал 00:20 отсутствует), я хочу, чтобы "точка_данных" возвращалась как 0

REPLACE , IF , IFNULL , ISNULL не работают, если не возвращено ни одной строки.

Я думал, что Union со значением по умолчанию будет работать, но он тоже не удался или, может быть, я использовал его неправильно.

Есть ли способ сделать это только через sql?

Примечание: Python 2.6 и mysql версия 5.1

Ответы [ 3 ]

1 голос
/ 23 января 2010

Да, вы можете сделать это, используя только SQL. Решением будет использование хранимой процедуры. Нижеуказанная хранимая процедура дает следующий результат:

start   cnt
00:05:00   1
00:10:00   0
00:15:00   1
00:20:00   0
00:25:00   1
00:30:00   0
00:35:00   1
00:40:00   0
00:45:00   0
00:50:00   0
00:55:00   2

Таблица Я использовал:

CREATE TABLE `timedata` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `c1` datetime DEFAULT NULL,
  `c2` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
)

Здесь хранимая процедура (с учетом вашей среды):

DROP PROCEDURE IF EXISTS per5min;
DELIMITER //
CREATE PROCEDURE per5min ()
BEGIN
  DECLARE dtMin DATETIME;
  DECLARE dtMax DATETIME;
  DECLARE dtStart DATETIME;
  DECLARE dtStop DATETIME;
  DECLARE tmDiff TIME;
  DECLARE result INT UNSIGNED;
  SET @offset = 5 * 60;
  SELECT MIN(c1) into dtMin FROM timedata;
  SELECT MAX(c1) into dtMax FROM timedata;

  CREATE TEMPORARY TABLE tmp_per5min (
      start TIME,
      cnt INT UNSIGNED
  );

  SET dtStart = dtMin;
  REPEAT
    SELECT dtStart + INTERVAL @offset SECOND into dtStop;
    SELECT count(c2) into result FROM timedata WHERE c1 BETWEEN dtStart and dtStop;
    SELECT TIME(SUBTIME(dtStop,TIME(dtMin))) into tmDiff;
    INSERT INTO tmp_per5min (start,cnt) VALUES (tmDiff,result);
    SET dtStart = dtStop;
  UNTIL dtStop >= dtMax END REPEAT;

  SELECT * FROM tmp_per5min;
  DROP TABLE tmp_per5min;
END;
//
DELIMITER ;

CALL per5min();

Если вы сохраните вышеприведенное в файл с именем per5minproc.sql, вы можете загрузить его следующим образом:

shell> mysql -uroot test < per5minproc.sql

В Python, использующем MySQLdb (я не работал в MySQL, Connector / Python, мне стыдно!):

import MySQLdb as m

if __name__ == '__main__':
    db = m.connect(user='root',db='test')
    c = db.cursor()
    c.callproc("per5min")
    print(c.fetchall())
    c.close()
    db.close()

Решение, приведенное выше, работает, но, вероятно, потребуется некоторая настройка, например dtStart может быть аргументом для SP. И это действительно все SQL!

0 голосов
/ 22 января 2010

Вы не можете запрашивать данные, которых у вас нет.

Вы (как мыслящий человек) можете утверждать, что данные в 00:20 отсутствуют; но нет простого способа определить «отсутствующий» в некотором более формальном смысле SQL.

Лучшее, что вы можете сделать, - это создать таблицу с ожидаемым временем.

Затем вы можете выполнить внешнее соединение между ожидаемым временем (включая 0 для 00:20) и фактическим временем (пропуская образец 00:20), и вы получите ожидаемый результат.

0 голосов
/ 22 января 2010

Я не вижу простого способа создания несуществующих записей из воздуха, но вы могли бы создать себе таблицу point_dates, содержащую все интересующие вас временные метки, и оставить ее в своих данных:

select pd.slot, IFNULL(data_point, 0) from point_dates pd left join some_table st on st.point_date=pd.slot where point_date >= start_date AND point_date < end_date order by point_date

...