我正在编写一个处理MySQL表的过程,该表的名称取决于当天,格式为cdr_20131108
。我的程序应该能够在任何给定日期的表格中进行一些操作。
所有这些表都具有相同的结构,并包含time
字段。对于每一行,我需要检查在前一小时内符合某些条件的行数。据我所知,我需要一个光标来查找当前行的时间,以及更多的数据,然后准备并执行一个查询,我将从中找到我的结果。
在伪代码中:
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `myproc`()
BEGIN
DECLARE all necessary variables to save the data returned by the cursor
DECLARE c1 cursor for
select required fields
from cdr_20131103
where some criteria;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET _done = TRUE;
set @tablename := concat('rm_cdrs',date_format(curdate(),'%Y%m%d'));
set @entries := 0;
open c1;
c1_loop: loop
fetch c1 into my variables;
if `_done` then leave c1_loop; end if;
set @q := concat('... my query is prepared here: select count(*) into @variable (
select in which i look for rows that meet my criteria that
happened less tan an hour before the one in the cursor)');
PREPARE stmt FROM @q; EXECUTE stmt; DEALLOCATE PREPARE stmt;
if some criteria is met then do some stuff...
end loop c1_loop;
close c1;
END
所以当我需要检查今天的表而不调整代码时,我的问题出现了,因为MySQL不允许我在这里使用变量:
DECLARE c1 cursor for
select required fields
from cdr_20131103
where some criteria;
我尝试使用正确的表名创建一个生成所需过程的过程,但MySQL不会让我从存储的例程中删除或更改过程。
在这种情况下是否有解决方法?
在这种情况下我可以避免使用光标吗?
我是否应该手动执行光标的任务,如here所述?
此过程可能会定期使用cron调用。我应该只编写一些创建的Java / C / PHP应用程序并在删除旧程序后调用正确的程序吗?
非常感谢!
修改
@Sebas表示可以使用单个insert-select语句执行此操作。虽然他的回答中的视图技巧就像一个魅力,但我想尝试从中学习。我将添加更多信息:
选择有趣的列并使用where子句过滤掉数据时,cdr_20131103
如下所示:
+---------+----------------+--------+
| user_ID | destination_ID | time |
+---------+----------------+--------+
| 2 | 56 | 110312 |
| 4 | 53 | 110513 |
| 2 | 56 | 110821 |
| 2 | 56 | 113212 | *
| 2 | 56 | 123001 |
+---------+----------------+--------+
我需要找出相同的user_ID何时在一小时内至少访问过3次相同的destination_ID。因此,应将*
行与一个now()字段一起插入另一个表中。
我的线性思维告诉我,我应该逐个处理行,计算初始时间(time - interval 1 hour
,在该时间间隔内选择具有相同User_ID和destination_ID的行,计算它们并最终将它们插入另一个表
在SQL中有更好的方法吗?
非常感谢你!
答案 0 :(得分:2)
我认为您可以使用一个select insert
SQL执行所有操作。调查这样的事情(假设tabletoinsert
,假设time
的列类型为VARCHAR
)
INSERT INTO tabletoinsert
SELECT user_id, destination_id, SUBSTRING(time, 1, 2) AS hour, NOW()
FROM cdr_20131103
GROUP BY user_id, destination_id, SUBSTRING(time, 1, 2)
HAVING COUNT(*) >= 3
但如果你真的需要光标,你也可以使用脏技巧:
1-在另一个存储过程中动态创建视图
SET @dyn_sql = CONCAT('CREATE OR REPLACE VIEW `v_yourview` AS ',
SELECT required fields
FROM cdr_', date_format(curdate(),'%Y%m%d'), ' WHERE some criteria;');
PREPARE stmt_dyn_view FROM @dyn_sql;
EXECUTE stmt_dyn_view;
DEALLOCATE PREPARE stmt_dyn_view;
2-在主程序的光标中使用它:
DECLARE c1 cursor for
select required fields
from v_yourview
where some criteria;