MySQL LOOP для сбора данных из нескольких таблиц - PullRequest
0 голосов
/ 24 июня 2011

Я огляделся и не могу найти решение, которое бы отвечало моим потребностям, поэтому я надеюсь, что вы поможете.(Я немного новичок в MySQL, хотя у меня достаточно опыта работы с SQL Server и Oracle.)

У меня есть база данных с несколькими таблицами.

Первая таблицаявляется таблицей определений, которая хранит основную информацию и называется cp_def:

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

Затем для каждой записи в таблице cp_def существует соответствующая таблица cp_ [cid] (где [cid] - значение cidиз таблицы cp_def).Пример:

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

Мне нужно запускать динамический запрос каждый день (как часть сценария оболочки и задания cron), чтобы вывести значения столбца code и date_expired для всех записей во всех таблицах cp_ [cid]где значение 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 голосов
/ 24 июня 2011

Прежде всего, почему данные cp_ разбиты на отдельные таблицы?Если бы данные были должным образом нормализованы, это не было бы проблемой.

При этом простое решение состояло бы в том, чтобы создать представление объединения всех таблиц cp_ - однако IME, mysql не оптимизирует push-предикатыдля представлений / подзапросов настолько эффективно, насколько это возможно.И как вы обнаружили, вам все еще нужно поддерживать представление.

Что приводит меня к использованию решения, описанного Devart.Заметим, что это не заменит нормализацию ваших данных!Это никогда не будет таким эффективным, и с увеличением количества таблиц производительность будет быстро снижаться.Однако Деварт пропустил скучный бит - как получить набор результатов из процедуры - короткий ответ, что вы не можете.Однако вы можете вставить соответствующие строки во временную таблицу, а затем выбрать строки из этого.

0 голосов
/ 09 мая 2013

Я нашел решение:

Сохраните запрос 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;
0 голосов
/ 24 июня 2011

Я бы предпочел иметь одну таблицу с такой структурой (вместо многих 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, затем выполняет сгенерированный запрос с подготовленными операторами .

EDIT

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;
...