MYSQL Select 从存储过程中的临时表加入不工作
MYSQL Select JOIN from temporary tables inside stored procedures not working
我在存储过程中遇到 select 连接问题。在该过程中,我创建了两个共享公用密钥 (t_id) 的临时 table K1 和 K2。每个只有一个值列。我想要做的是加入两个 tables 以检索一个 table 与键和两列与值。
K1table是这样的
--------------
t_id | KPI1
--------------
1 0.5
2 0.3
3 0.7
--------------
K2table是这样的
--------------
t_id | KPI2
--------------
1 0.4
2 0.2
3 0.1
--------------
预期结果是这样的:
--------------------
t_id | KPI1 | KPI2
--------------------
1 0.5 0.4
2 0.3 0.2
3 0.7 0.1
--------------------
如果我 运行 在常规查询中使用此代码,它将完美运行:
set @t_ini = '2020-07-01 00:00:00';
set @t_end = '2020-07-04 00:00:00';
create temporary table K12 (t_id int,KPI1 float, KPI2 float);
-- get KPI1 in a temporary table
create temporary table K1 as
select distinct intervaldate.ID as t_id,Value as KPI1
from
kpi_db,intervaldate,controllers
where
kpi_db.Interval_ID = intervaldate.ID and
kpi_db.Ctrl_ID = controllers.ID and
kpi_db.Ctrl_ID = CtrlID and
intervaldate.TStart between @t_ini and @t_end and
kpi_db.KPI_ID = 1;
-- get KPI2 in a temporary table
create temporary table K2 as
select distinct distinct intervaldate.ID as t_id,Value as KPI2
from
kpi_db,intervaldate,controllers
where
kpi_db.Interval_ID = intervaldate.ID and
kpi_db.Ctrl_ID = controllers.ID and
kpi_db.Ctrl_ID = CtrlID and
intervaldate.TStart between @t_ini and @t_end and
kpi_db.KPI_ID = 2;
-- merge the two temporary tables
insert into K12(t_id,KPI1,KPI2)
select K1.t_id,KPI1,KPI2
from K1
left join
K2
on (K1.t_id = K2.t_id);
select * from K12;
但是当我把它放在存储过程中时,K12 returns 只是空值
--------------------
t_id | KPI1 | KPI2
--------------------
1 Null Null
2 Null Null
3 Null Null
--------------------
存储过程如下
CREATE DEFINER=`root`@`localhost` PROCEDURE `UpdateKPIs1_2`(CtrlID int,EventID int,PCT float)
BEGIN
declare done int default 0;
declare t_ini datetime;
declare t_end datetime;
declare t_id int;
declare kpi1 float;
declare kpi2 float;
declare kpi1_nc float;
declare kpi1_new float;
-- cursors declaration
declare cursor_KPIs cursor for select * from K12;
declare continue handler for not found set done = true;
-- temporary table declaration
create temporary table K12 (t_id int,KPI1 float, KPI2 float);
-- select t_ini and t_end
set t_ini = date((select Turn_OFF from turn_on_off where ID = EventID));
set t_end = date((select Turn_ON from turn_on_off where ID = EventID));
-- get KPI1 in a temporary table
create temporary table K1 as
select distinct intervaldate.ID as t_id,Value as KPI1
from
kpi_db,intervaldate,controllers
where
kpi_db.Interval_ID = intervaldate.ID and
kpi_db.Ctrl_ID = controllers.ID and
kpi_db.Ctrl_ID = CtrlID and
intervaldate.TStart between t_ini and t_end and
kpi_db.KPI_ID = 1;
-- get KPI2 in a temporary table
create temporary table K2 as
select distinct distinct intervaldate.ID as t_id,Value as KPI2
from
kpi_db,intervaldate,controllers
where
kpi_db.Interval_ID = intervaldate.ID and
kpi_db.Ctrl_ID = controllers.ID and
kpi_db.Ctrl_ID = CtrlID and
intervaldate.TStart between t_ini and t_end and
kpi_db.KPI_ID = 2;
-- merge the two temporary tables
insert into K12(t_id,KPI1,KPI2)
select K1.t_id,KPI1,KPI2
from K1
left join
K2
on (K1.t_id = K2.t_id);
-- iterate over the K12 temporary table
open cursor_KPIs;
select * from K1;
select * from K2;
select * from K12;
-- HERE COMES SOME PROCESSING USING THE CURSOR. I droped it
-- to make the script more clear.
drop table K1;
drop table K2;
drop table K12;
-- close cursor
close cursor_KPIs;
END
我想知道这个问题是否与分隔符有关,但我不知道如何在此处正确设置分隔符。
我认为我在这里做了一些非常愚蠢的事情,但我看不到它。
谢谢。
看来你把这里的事情复杂化了:
两个查询几乎相同 - 只有 where
子句不同 - 你可以在单个查询中获得相同的结果,使用条件聚合
我不明白临时 tables 的意义;您可以直接从查询结果
中插入目标 table
我想这样的东西应该很接近你想要的:
insert into k12(t_id, kpi1, kpi2)
select
i.id as t_id,
max(case when k.kpi_id = 1 then k.value end) as kpi1,
max(case when k.kpi_id = 2 then k.value end) as kpi2
from kpi_db k
inner join intervaldate i on k.interval_id = i.id
inner join controllers c on k.ctrl_id = c.id
where i.tstart between @t_ini and @t_end and k.kpi_id in (1, 2)
group by i.id;
有趣的线程!
我想知道是否可以在 function/procedure 中生成一个临时 table,随后可以将其用于加入表达式,例如
(关闭语法检查!)
FUNCTION CreateTS(DATETIME from, DATETIME to, INT intervalSec)
BEGIN
-- create temp table having records
-- 1,(from, from+intervalSec),
-- 2,(from+intervalSec,from+intervalSec*2),
-- ...,
-- n,(to-intervalSec,to)
return resultset
END
用于
等查询
SELECT ts.from,ts.to,(some aggregating expression based on t1)
FROM CreateTS(DATE_SUB(NOW(),30,day),NOW(),3600) ts
JOIN T1 t1 on t1.datetime >= ts.from AND t1.datetime < ts.to
理想情况下 SQL 有一个虚拟时间尺度 table 可以用作
SELECT * FROM timescale ts WHERE ts.from >= ... and ts.to < ... and ts.type = week
其中类型可以是所有正常的秒、分、时、日、周、月、年
所以上面的例子可以是
SELECT ts.from,ts.to,(some aggregating expression based on t1)
FROM TS ts
JOIN T1 t1 on t1.datetime >= ts.from AND t1.datetime < ts.to
WHERE ts.from = DATE_SUB(NOW(),30,day) and ts.to = NOW() and ts.type=hour
谢谢
我在存储过程中遇到 select 连接问题。在该过程中,我创建了两个共享公用密钥 (t_id) 的临时 table K1 和 K2。每个只有一个值列。我想要做的是加入两个 tables 以检索一个 table 与键和两列与值。
K1table是这样的
--------------
t_id | KPI1
--------------
1 0.5
2 0.3
3 0.7
--------------
K2table是这样的
--------------
t_id | KPI2
--------------
1 0.4
2 0.2
3 0.1
--------------
预期结果是这样的:
--------------------
t_id | KPI1 | KPI2
--------------------
1 0.5 0.4
2 0.3 0.2
3 0.7 0.1
--------------------
如果我 运行 在常规查询中使用此代码,它将完美运行:
set @t_ini = '2020-07-01 00:00:00';
set @t_end = '2020-07-04 00:00:00';
create temporary table K12 (t_id int,KPI1 float, KPI2 float);
-- get KPI1 in a temporary table
create temporary table K1 as
select distinct intervaldate.ID as t_id,Value as KPI1
from
kpi_db,intervaldate,controllers
where
kpi_db.Interval_ID = intervaldate.ID and
kpi_db.Ctrl_ID = controllers.ID and
kpi_db.Ctrl_ID = CtrlID and
intervaldate.TStart between @t_ini and @t_end and
kpi_db.KPI_ID = 1;
-- get KPI2 in a temporary table
create temporary table K2 as
select distinct distinct intervaldate.ID as t_id,Value as KPI2
from
kpi_db,intervaldate,controllers
where
kpi_db.Interval_ID = intervaldate.ID and
kpi_db.Ctrl_ID = controllers.ID and
kpi_db.Ctrl_ID = CtrlID and
intervaldate.TStart between @t_ini and @t_end and
kpi_db.KPI_ID = 2;
-- merge the two temporary tables
insert into K12(t_id,KPI1,KPI2)
select K1.t_id,KPI1,KPI2
from K1
left join
K2
on (K1.t_id = K2.t_id);
select * from K12;
但是当我把它放在存储过程中时,K12 returns 只是空值
--------------------
t_id | KPI1 | KPI2
--------------------
1 Null Null
2 Null Null
3 Null Null
--------------------
存储过程如下
CREATE DEFINER=`root`@`localhost` PROCEDURE `UpdateKPIs1_2`(CtrlID int,EventID int,PCT float)
BEGIN
declare done int default 0;
declare t_ini datetime;
declare t_end datetime;
declare t_id int;
declare kpi1 float;
declare kpi2 float;
declare kpi1_nc float;
declare kpi1_new float;
-- cursors declaration
declare cursor_KPIs cursor for select * from K12;
declare continue handler for not found set done = true;
-- temporary table declaration
create temporary table K12 (t_id int,KPI1 float, KPI2 float);
-- select t_ini and t_end
set t_ini = date((select Turn_OFF from turn_on_off where ID = EventID));
set t_end = date((select Turn_ON from turn_on_off where ID = EventID));
-- get KPI1 in a temporary table
create temporary table K1 as
select distinct intervaldate.ID as t_id,Value as KPI1
from
kpi_db,intervaldate,controllers
where
kpi_db.Interval_ID = intervaldate.ID and
kpi_db.Ctrl_ID = controllers.ID and
kpi_db.Ctrl_ID = CtrlID and
intervaldate.TStart between t_ini and t_end and
kpi_db.KPI_ID = 1;
-- get KPI2 in a temporary table
create temporary table K2 as
select distinct distinct intervaldate.ID as t_id,Value as KPI2
from
kpi_db,intervaldate,controllers
where
kpi_db.Interval_ID = intervaldate.ID and
kpi_db.Ctrl_ID = controllers.ID and
kpi_db.Ctrl_ID = CtrlID and
intervaldate.TStart between t_ini and t_end and
kpi_db.KPI_ID = 2;
-- merge the two temporary tables
insert into K12(t_id,KPI1,KPI2)
select K1.t_id,KPI1,KPI2
from K1
left join
K2
on (K1.t_id = K2.t_id);
-- iterate over the K12 temporary table
open cursor_KPIs;
select * from K1;
select * from K2;
select * from K12;
-- HERE COMES SOME PROCESSING USING THE CURSOR. I droped it
-- to make the script more clear.
drop table K1;
drop table K2;
drop table K12;
-- close cursor
close cursor_KPIs;
END
我想知道这个问题是否与分隔符有关,但我不知道如何在此处正确设置分隔符。
我认为我在这里做了一些非常愚蠢的事情,但我看不到它。
谢谢。
看来你把这里的事情复杂化了:
两个查询几乎相同 - 只有
where
子句不同 - 你可以在单个查询中获得相同的结果,使用条件聚合我不明白临时 tables 的意义;您可以直接从查询结果
中插入目标 table
我想这样的东西应该很接近你想要的:
insert into k12(t_id, kpi1, kpi2)
select
i.id as t_id,
max(case when k.kpi_id = 1 then k.value end) as kpi1,
max(case when k.kpi_id = 2 then k.value end) as kpi2
from kpi_db k
inner join intervaldate i on k.interval_id = i.id
inner join controllers c on k.ctrl_id = c.id
where i.tstart between @t_ini and @t_end and k.kpi_id in (1, 2)
group by i.id;
有趣的线程!
我想知道是否可以在 function/procedure 中生成一个临时 table,随后可以将其用于加入表达式,例如
(关闭语法检查!)
FUNCTION CreateTS(DATETIME from, DATETIME to, INT intervalSec)
BEGIN
-- create temp table having records
-- 1,(from, from+intervalSec),
-- 2,(from+intervalSec,from+intervalSec*2),
-- ...,
-- n,(to-intervalSec,to)
return resultset
END
用于
等查询SELECT ts.from,ts.to,(some aggregating expression based on t1)
FROM CreateTS(DATE_SUB(NOW(),30,day),NOW(),3600) ts
JOIN T1 t1 on t1.datetime >= ts.from AND t1.datetime < ts.to
理想情况下 SQL 有一个虚拟时间尺度 table 可以用作
SELECT * FROM timescale ts WHERE ts.from >= ... and ts.to < ... and ts.type = week
其中类型可以是所有正常的秒、分、时、日、周、月、年
所以上面的例子可以是
SELECT ts.from,ts.to,(some aggregating expression based on t1)
FROM TS ts
JOIN T1 t1 on t1.datetime >= ts.from AND t1.datetime < ts.to
WHERE ts.from = DATE_SUB(NOW(),30,day) and ts.to = NOW() and ts.type=hour
谢谢