MySQL LOOP用于从多个表中收集数据

时间:2011-06-24 04:29:03

标签: mysql sql view union-all

我环顾四周,似乎无法找到满足我需求的解决方案,所以我希望你能提供帮助。 (我对MySQL有些新手,虽然我确实有大量的SQL Server和Oracle经验可供借鉴。)

我有一个包含多个表的数据库。

第一个表是存储基本信息的定义表,称为cp_def:

cid (pkey)  status
-------------------
10001       0
10002       1

然后,对于cp_def表中的每个记录,都有一个对应的cp_ [cid]表(其中[cid]是来自cp_def表的cid值)。例如:

table: cp_10001

id(pkey)   code      date_issued    date_expired
-------------------------------------------------
1          ABC123    2011-06-23     2011-06-30
2          CYG124    2011-06-23     2011-06-30


table: cp_10002

id(pkey)   code      date_issued    date_expired
-------------------------------------------------
1          CAC126    2011-06-23     2011-06-30
2          VGC254    2011-06-23     2011-06-30

我需要每天运行一个动态查询(作为shell脚本和cron作业的一部分),为所有cp_ [cid]表中的所有记录输出code和date_expired列值,其中date_issued值是前一个一天的约会。

我有一个查询工作(见下文)。但是,每次添加新的cp_ [CID]表时,都需要我手动将另一个UNION ALL语句附加到查询的末尾。

SELECT code, date_expired
FROM mydatabase.cp_10001
WHERE DATE(date_issued) = DATE_SUB(CURDATE(), INTERVAL 1 DAY);
UNION ALL
SELECT code, date_expired
FROM mydatabase.cp_10002
WHERE DATE(date_issued) = DATE_SUB(CURDATE(), INTERVAL 1 DAY);  

我的最终目标是在执行时以编程方式生成上述查询,以便每次将新的cp_ [CID]表添加到数据库时,都不需要手动干预。

我尝试使用视图。但是,似乎添加一个表仍需要手动更改视图,以便考虑新表。

鉴于每个cp_ [CID]表都列在cp_def表中(以及INFORMATION_SCHEMA表),我认为我可以执行某种循环来构建动态查询,但我还没有想到出来。为了保持这个简短,我将避免发布我在循环通过cp_def表创建动态查询的失败尝试。

您可以提供任何帮助,指出我正在制定此类查询的正确方向,我们将不胜感激。如果我忽略了某些事情,我会道歉。我已经尝试用很多不同的短语搜索我正在寻找的东西,但没有用。

3 个答案:

答案 0 :(得分:0)

我更喜欢有一个像这样的结构的表(而不是很多cp _ ####) -

cp_properties:
id(pkey), cid(foreign key to cp_def.cid) , code      date_issued    date_expired

但是对于您的设计,请尝试此查询 -

SELECT GROUP_CONCAT(CONCAT('SELECT code, date_expired FROM mydatabase.cp_', cid, ' WHERE DATE(date_issued) = DATE_SUB(CURDATE(), INTERVAL 1 DAY)') SEPARATOR '\r\nUNION ALL\r\n') FROM mydatabase.cp_def

此查询使用UNION ALL子句生成select语句,然后使用prepared statements执行生成的查询。

修改

SELECT GROUP_CONCAT(CONCAT('SELECT code, date_expired FROM mydatabase.cp_', cid, ' WHERE DATE(date_issued) = DATE_SUB(CURDATE(), INTERVAL 1 DAY)') SEPARATOR '\r\nUNION ALL\r\n') INTO @s FROM mydatabase.cp_def;
PREPARE stmt FROM @s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

答案 1 :(得分:0)

首先,为什么将cp_数据拆分成单独的表?如果数据正确标准化,这将不是问题。

Givn,一个简单的解决方案是创建所有cp_表的联合视图 - 但是IME,mysql并不像它可能那样有效地优化视图/子查询的推送谓词。正如您所发现的,您仍然需要维护视图。

这使我使用Devart描述的解决方案。 Noet,这不能代替规范化您的数据!它永远不会那么高效,并且随着表数量的增加,性能将迅速降低。然而Devart已经跳过了这个小小的问题 - 如何将结果集从程序中删除 - 简短的回答是你做不到。但是,您可以将匹配的行插入临时表,然后从中选择行。

答案 2 :(得分:0)

我找到了解决方案:

将表上的UNION ALL查询保存到@s并创建一个视图以保存表组合的结果。

Select group_concat(concat('select * from new_schema.', name ) separator '\r\nUNION 
ALL\r\n')
into @s from new_schema.tempTableName;
set @v = concat('create View view as ', @s);
PREPARE stmt FROM @v;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;