python:mysql:找不到行时返回0

时间:2010-01-22 17:28:45

标签: python mysql null

表结构 - 数据存在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
from some_table
where point_date >= start_date
AND point_date < end_date
order by point_date

现在,当我没有特定时段的条目时(例如,缺少时间段00:20),我希望“data_point”返回为0

REPLACE IF IFNULL ISNULL 在没有返回任何行时不起作用。< / p>

我认为使用默认值的Union会起作用,但它也失败了,或者我没有正确使用它。

有没有办法只通过sql完成这项工作?

注意: Python 2.6&amp; mysql版本5.1

3 个答案:

答案 0 :(得分:1)

是的,你可以只用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!

答案 1 :(得分:0)

我认为没有简单的方法可以凭空创建不存在的记录,但您可以自己创建一个包含您感兴趣的所有时间戳的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

答案 2 :(得分:0)

您无法查询您没有的数据。

你(作为有思想的人)可以声称缺少00:20的数据;但是在一些更正式的SQL意义上,没有简单的方法来定义“缺失”。

您可以做的最好的事情是创建一个包含所有预期时间的表格。

然后你可以在预期的时间(包括00:20的0)和实际的时间(缺少00:20样本)之间进行外连接,你会得到你期望的结果。