[MYSQL]查询单位时间消耗量

文章描述了一个MySQL数据库操作过程,包括创建表结构、查询上一小时和一天的数据消耗量,以及生成随机数据并存储到数据源和汇总表中。作者寻求对查询语句进行优化以提高效率。
摘要由CSDN通过智能技术生成

请求哪位大神给我优化一下mysql语句.

数据库表:(日/月/年 数据表和data_hour结构一样,懒得复制了,不然太长)


DROP TABLE IF EXISTS data_source;#数据源
create table IF not EXISTS  data_source (
num  int unsigned  not null auto_increment PRIMARY KEY   COMMENT'序号   值唯一',
id  varchar(40)  not null  COMMENT 'ID',
data_current  DOUBLE COMMENT '瞬时数据  随时间累加或不变',
data_time    TIMESTAMP COMMENT '数据时间'
)charset=gb2312;


DROP TABLE IF EXISTS data_hour;#YH_ES 小时数据汇总
create table IF not EXISTS  data_hour (
num  int unsigned  not null auto_increment PRIMARY KEY   COMMENT'序号   值唯一',
id  varchar(40)  not null  COMMENT 'ID',
data_s   DOUBLE COMMENT '起始读数',
data_e   DOUBLE COMMENT '末期读数',
hour_data   DOUBLE COMMENT '小时消耗量',
s_time   TIMESTAMP COMMENT '起始读数时间',
e_time   TIMESTAMP COMMENT '期末读数时间'
)charset=gb2312;

查询上一小时消耗量:

计算方法1.当前小时最小时间对应读数 - 上一小时最小时间对应读数

计算方法2.上一小时最大时间对应读数 - 上一小时最小时间对应读数(没做,误差太大,上一小时最大时间对应读数和当前小时最小时间对应读数之间差值没有统计在内.)

方法1实现:

SET @time_result=DATE_FORMAT(DATE_SUB(CURRENT_TIME(),INTERVAL -1 HOUR),'%Y-%m-%d %H');
SET @time_now=DATE_FORMAT(CURRENT_TIME(),'%Y-%m-%d %H');
INSERT INTO test.data_hour ( id, 
data_s,   data_e,   hour_data,
s_time, e_time) 	
SELECT te.id, 
ts.data_current AS data_s,te.data_current AS data_e,
ROUND((te.data_current -ts.data_current),3) AS hour_data,
ts.data_time AS s_time,te.data_time AS e_time FROM
	(SELECT a.id,a.data_current,a.data_time from data_source AS a 
	INNER   JOIN (SELECT m.id id, MIN(m.data_time) min_time from data_source AS m
	WHERE  DATE_FORMAT(data_time,'%Y-%m-%d %H') = @time_result
	GROUP BY id)AS f ON  a.data_time=f.min_time AND a.id=f.id GROUP BY a.id ) AS ts,
	(SELECT a.id,a.data_current,a.data_time  from data_source AS a 
	INNER   JOIN (SELECT m.id id, MIN(m.data_time) min_time from data_source AS m
	WHERE  DATE_FORMAT(data_time,'%Y-%m-%d %H') =@time_now
	GROUP BY id)AS f ON  a.data_time=f.min_time AND a.id=f.id GROUP BY a.id )
AS te WHERE ts.id=te.id;

同理,查询上一天消耗量:

SET @time_result=DATE_FORMAT(DATE_SUB(CURRENT_TIME(),INTERVAL 1 DAY),'%Y-%m-%d');
-- INSERT INTO test.data_day ( id, 
-- data_s,   data_e,   day_data,
-- s_time, e_time) 	
	SELECT te.id,	ts.data_s as data_s,	te.data_e as data_e,
	ROUND((te.data_e -ts.data_s),3) as day_data,
	ts.s_time as s_time,te.e_time as e_time FROM
			(SELECT a.id,a.data_s,a.s_time from data_hour as a 
			INNER   JOIN (SELECT MIN(m.s_time) min_time from data_hour as m
			WHERE  DATE_FORMAT(s_time,'%Y-%m-%d') = @time_result GROUP BY id)as f
			on  a.s_time=f.min_time GROUP BY a.id  ORDER BY  a.id) as ts,
			(SELECT a.id,a.data_e,a.e_time  from data_hour as a 
			INNER   JOIN (SELECT MAX(m.e_time) max_time from data_hour as m
			WHERE  DATE_FORMAT(s_time,'%Y-%m-%d') = @time_result GROUP BY id)as f
			on  a.e_time=f.max_time GROUP BY a.id  ORDER BY  a.id)
	 as te WHERE ts.id=te.id;

同理可算月/年数据

测试:

插入数据:

#define MFT(format,...) std_string_format(format,##__VA_ARGS__)

std::string  std_string_format( const char * _Format, ...) {
	std::string tmp;
	va_list marker = NULL;
	va_start(marker, _Format);
	size_t num_of_chars = _vscprintf(_Format, marker);
	if (num_of_chars >= tmp.capacity()) 
	{
		tmp.resize(num_of_chars + 1);
	}
	vsprintf_s((char *)tmp.data(), tmp.capacity(), _Format, marker);
	va_end(marker);
	string strRet(tmp.data());
	return strRet;
}


/***********
*获取随机数值
*DWORD pt=1, 随机数种子,默认为传入的时间戳
*int min=0,   产生的随机数最小值
*int max=100 ,产生的随机数最大值
*DWORD t=0 ,  防止在循环中使用时候产生的随机数一样
*float dot=0.1f 转换为float的倍数
*返回:随机数
************/
float GetFloatRandValue(DWORD pt=1,int min=0,int max=100 ,DWORD t=0 ,float dot=0.1f)
{
	if (pt==0)
	{
		pt=GetTickCount();
	}
	srand(pt+t);
	float v=(rand()%(max-min+1)+min)*dot;
	return v;

}

/******************
*制作小时数据 一个小时三条数据
*CTools *sqlTool, 数据库操作类指针
*CTime ts,   起始时间 包含
*CTime te,   期末时间  包含
*std::vector<std::string> mAlldev, 设备ID
*返回:无
*********************/
void  SetDataToDB(CTools *sqlTool,CTime ts,CTime te,std::vector<std::string> mAlldev)
{
	float fDataCurrent=0.0f;	//"瞬时数据"
	string strClearSql="TRUNCATE  test.data_source; ";
	sqlTool->delete_sql(strClearSql.data());
	DWORD pt=GetTickCount();
	int n =0;
	CTimeSpan  tsp=te-ts;
	int allMin =(int)tsp.GetTotalMinutes();
	for (int minute = 0; minute <= allMin; minute+=30)
	{
		CTimeSpan  dtsp(0,0,minute,0);
		CTime  tData=ts+dtsp;
		for (int i = 0; i <(int) mAlldev.size(); i++)
		{
			fDataCurrent+=GetFloatRandValue(pt,10,110, n++);
			string mTime=MFT2("%d-%02d-%02d %02d:%02d:%02d",tData.GetYear(),tData.GetMonth(),tData.GetDay(),tData.GetHour(),tData.GetMinute(),n%60);
			string sDevId=mAlldev[i];
			string sqlStr=MFT2("INSERT INTO test.data_source "
					"(id,data_current, data_time) "
					" VALUES ('%s',%.1f, '%s');",
					sDevId.data(),fDataCurrent,mTime.data()
					);
			sqlTool->insert_sql(sqlStr.data());
		}
	}

}

/******************
*计算小时差值,并存入数据库
*CTools *sqlTool, 数据库操作类指针
*CTime ts,   起始时间 包含
*CTime te,   期末时间  包含
*返回:无
**************************/
void CalculateDataOfHour(CTools *sqlTool,CTime ts,CTime te)
{
	string strClearSql="TRUNCATE test.data_hour;";
	sqlTool->delete_sql(strClearSql.data());
	CTimeSpan  tsp=te-ts;
	string sTimeStart=GetTimeStringOfHour(ts);
	int allHour =(int)tsp.GetTotalHours();
	for (int hour = 0; hour <allHour; hour++)
	{
		CTimeSpan tHsp(0,1,0,0);
		ts+=tHsp;
		string sTimeEnd=GetTimeStringOfHour(ts);
		MTRACE("起始:%s  期末:%s\n",sTimeStart.data(),sTimeEnd.data());
		string sqlStr =MFT("INSERT INTO test.data_hour ( id, \n"
							"data_s,   data_e,   hour_data,\n"
							"s_time, e_time) 	\n"
							"	SELECT te.id, \n"
							"	ts.data_current as data_s,te.data_current as data_e,\n"
							"	ROUND((te.data_current -ts.data_current),3) as hour_data,\n"
							"	ts.data_time as s_time,te.data_time as e_time FROM\n"
							"			(SELECT a.id,a.data_current,a.data_time from data_source as a \n"
							"			INNER   JOIN (SELECT MIN(m.data_time) min_time from data_source as m\n"
							"			WHERE  DATE_FORMAT(data_time,'%%Y-%%m-%%d %%H') = '%s' GROUP BY id)as f\n"
							"			on  a.data_time=f.min_time GROUP BY a.id  ORDER BY  a.id) as ts,\n"
							"			(SELECT a.id,a.data_current,a.data_time  from data_source as a \n"
							"			INNER   JOIN (SELECT MIN(m.data_time) min_time from data_source as m\n"
							"			WHERE  DATE_FORMAT(data_time,'%%Y-%%m-%%d %%H') = '%s' GROUP BY id)as f\n"
							"			on  a.data_time=f.min_time GROUP BY a.id  ORDER BY  a.id)\n"
							"	 as te WHERE ts.id=te.id;",sTimeStart.data(),sTimeEnd.data());
		sqlTool->insert_sql(sqlStr.data());
		sTimeStart=sTimeEnd;
	}
}



int _tmain(int argc, _TCHAR* argv[])
{
	
	CTools *sqlTool=new CTools();
	if(!initMysql(sqlTool,"test"))
	{
		printf_s("数据库初始化失败\n");
		delete sqlTool;
		sqlTool=nullptr;
		return 1;
	}
	CTime ts(2023,1,1,0,0,0);
	CTime te(2024,2,1,0,0,0);
	std::vector<std::string> mAlldev;
	mAlldev.push_back("id_1");
	mAlldev.push_back("id_2");
	SetDataToDB(sqlTool,ts,te,mAlldev);
	CalculateDataOfHour(sqlTool,ts,te);
	//CalculateDataOfDay(sqlTool,ts,te);
	system("pause");
	delete sqlTool;
	return 0;
}

结果

1.单小时计算:

 

 按天

 

### 回答1: MySQL 查询数据库数据表时报 Error 2013 (HY000) 是由于超时引起的错误。这个错误通常是因为 SQL 查询操作耗费的时间超过了 MySQL 连接的最大超时时间限制所导致的。 解决这个问题可以通过以下几种方法: 1. 增加超时时间:可以在查询之前使用 SET GLOBAL connect_timeout=xxxx 来增加 MySQL 连接的超时时间,其中 xxxx 是一个较大的时间值,单位是秒。例如,可以设置为 3600 表示一小时的超时时间。 2. 优化查询语句:查找导致查询耗时过长的原因,尝试优化查询语句,减少查询所需的时间。可以通过添加索引、优化 SQL 查询语句、减少返回的结果集大小等方式来改善查询性能。 3. 分批查询:如果查询数据量过大,可以使用 LIMIT 和 OFFSET 进行分批查询,每次查询一部分数据,避免一次性查询过多数据导致超时。 4. 增加服务器资源:如果以上方法无法解决问题,可以考虑增加服务器的硬件资源,如增加内存、升级 CPU 等,以提高数据库的性能和处理能力。 需要注意的是,解决 Error 2013 (HY000) 错误不一定只有固定的方法,具体需要结合具体情况进行调整和优化。可以根据实际情况选择适合的方法,同时结合 MySQL 的日志和性能监控工具进行问题排查和优化。 ### 回答2: MySQL查询数据库数据表时报error 2013(HY000)错误一般是因为查询所花费的时间超过了MySQL服务器设置的最大连接超时时间。解决该问题可以通过以下几种方法: 1. 增加最大连接超时时间:可以通过修改MySQL服务器的配置文件my.cnf(或my.ini)来增加最大连接超时时间。找到[mysqld]部分,在下面添加或修改以下行: wait_timeout = 600 interactive_timeout = 600 这样的设置将最大连接超时时间设置为600秒。 2. 优化查询语句:如果查询语句复杂或者是对大数据表进行全表扫描,可以尝试进行查询语句的优化,例如添加索引、合理使用JOIN语句等。这样可以减少查询所需的时间,避免超时错误。 3. 增加服务器资源:如果查询数据表时仍然出现超时错误,可能是服务器资源不足导致的。此时可以考虑增加服务器的物理内存、CPU等资源,使服务器能够更快地处理查询请求。 4. 分批查询:如果大数据表无法通过以上方法解决超时问题,可以尝试将查询任务分成多个较小的批次来进行查询。通过遍历整个数据表,每次查询一部分数据,然后再将结果进行合并,可以避免一次性查询大量数据导致超时错误。 总之,解决MySQL查询数据表超时错误可以通过增加最大连接超时时间、优化查询语句、增加服务器资源以及分批查询等方法。根据具体情况选择合适的解决方案来解决该问题。 ### 回答3: 当我们在MySQL查询一个大数据表时,有时会遇到错误2013(HY000)。这个错误通常是由于查询超时引起的。 查询数据表时,数据库需要处理大量的数据消耗时间可能会比较长。默认情况下,MySQL设置了查询的超时时间为30秒。如果查询时间超过了这个限制,就会报错2013。 解决这个问题的方法有几种: 1. 增加查询的超时时间:可以通过修改MySQL配置文件中的wait_timeout参数来增加查询的超时时间。将其设置为一个更大的值,例如300秒。 2. 优化查询语句:通过分析查询语句,优化数据库的索引、表结构以及查询计划,提高查询效率。可以使用EXPLAIN命令来查看查询计划,找到导致查询缓慢的原因,然后进行相应的优化。 3. 分页查询:如果需要查询数据表中的大量数据,可以考虑使用分页查询的方式,每次查询一部分数据。这样可以减少单次查询数据量,提高查询效率。 4. 使用索引:对于经常用到的查询条件,可以考虑给相关字段添加索引。索引可以加快查询速度,减少查询时间。 5. 使用缓存:如果查询结果不是实时需要的,可以考虑使用缓存技术,将查询结果缓存在内存中。这样可以避免每次查询都要从数据库中读取数据,加快查询速度。 总的来说,解决MySQL查询数据表报错2013的方法主要是通过增加查询超时时间、优化查询语句、使用分页查询、添加索引以及使用缓存等方式来提高查询效率,避免超时错误的发生。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值