2013-10-12 3 views
0

Что-то, с чем я спотыкался какое-то время. У меня есть таблица под названием gears, которая содержит строки с именами: id, mid, cid и installed. Я хочу искать эту таблицу и возвращать в формате csv список mid s для некоторых уникальных cid. Например, если cid = $cid я могу использовать:Динамический запрос MySQL: присоединяйтесь к результатам из многочисленных таблиц

$query = $database -> query("SELECT COUNT(mid), GROUP_CONCAT(mid) FROM gears WHERE cid=$cid", __LINE__, __FILE__); 
$gears_installed = $database -> get_result($query); 
$gears = $database -> get_result($query, 0, 1); 

Не беспокойтесь об именах функций, они делают именно так, как можно было бы ожидать. Так что если бы было 3 ряда для этой конкретной $cid, с mid с: bank, lottery и post тогда $gears_installed будет равно 3 и $gears будет равна bank,lottery,post. Это работает по назначению.

Теперь на вопрос у меня есть. Каждый уникальный mid имеет свою собственную таблицу, названную settings_mid_here. I.e, для вышеупомянутых трех я имею таблицы settings_bank, settings_lottery и, наконец, settings_post. Каждая из этих таблиц также будет иметь столбец, называемый cid (так они могут быть связаны между собой). Как мне запустить один запрос, чтобы вернуть всю строку из каждой таблицы, где cid=$cid? Я не хочу запускать отдельный запрос для SELECT * FROM settings_bank WHERE cid=$cid и SELECT * FROM settings_post WHERE cid=$cid и, наконец, SELECT * FROM settings_post WHERE cid=$cid, так как это может привести к появлению около 10 дополнительных запросов при загрузке одной страницы (на данный момент 10 разных mid).

Как вы можете видеть, проблема динамична. Он должен иметь возможность адаптироваться к другому номеру mid s, каким-то образом различать настройки в каждой таблице (например, settings_bank может иметь столбец с именем name, и поэтому может быть settings_post). Наконец, он также должен иметь возможность возвращать строку по умолчанию (а не нулевые значения), если не существует строки, соответствующей заданному $cid.

Сложная задача, но я надеюсь, что кто-то может помочь мне в этом, так как я не смог никуда добраться.

+0

У меня есть некоторые идеи, но я мог бы только помочь, если бы у меня была дамп некоторой схемы и некоторых демо-данных для проверки запросов. В противном случае это просто разумная догадка. – Fleshgrinder

+0

Вы имеете в виду, что вы создадите новую таблицу каждый раз, когда в таблице 'gears' появится новая' mid'? – geomagas

+0

http://sqlfiddle.com/#!2/cc5ce/1 Использование cid = 3 –

ответ

1
$queries = array(); 
foreach(explode(',', $gears) as $gear) { 
    $queries[] = "SELECT '$gear' AS gearname, settings_$gear.* FROM settings_$gear WHERE cid=$cid"; 
} 
$sql = implode(' UNION ', $queries); 
$query2 = $database->query($sql); 

Этот запрос возвращает одну строку для каждой таблицы, с дополнительным gearname столбца, чтобы указать, какая таблица эта строка взялось.

Или вы можете создать РЕГИСТРИРУЙТЕСЬ динамически:

$gears_array = explode(',', $gears); 
$joins = implode(' JOIN ', $gears_array); 
$wheres = implode(' AND ', 
        array_map(function($g) use ($cid) { 
        return "$g.cid = $cid"; 
        }, $gears_array)); 
$sql = "SELECT * FROM $joins WHERE $wheres"; 
$query2 = $database->query($sql); 
+0

Я запустил это для тестового примера: 'SELECT 'currency' AS gearname, * FROM settings_currency WHERE cid = 3' , но это дает ошибку (из-за части' 'currency 'AS gearname'). –

+0

Исправлено. При этом MySQL требует явного tablename перед '*'. – Barmar

+0

Это отлично работает, пока две таблицы не имеют различного количества столбцов (что имеет место для меня) - в этот момент он разваливается и выдает ошибку. –

0

Это на самом деле не ответ на конкретный вопрос, просто потому, что нет никакого способа, чтобы сделать то, что вы пытаетесь с одним запросом.

Причина проста: РСУБД не предназначены для работы таким образом. В таблицах должны храниться данные, которые представляют предприятиями и отношениями. В вашем случае для каждого отдельного значения mid должна существовать таблица с именем settings_{mid}, заставляя столбец mid неявно хранить (часть) имя таблицы. Но это не данные, это метаданные.

Это не было бы проблемой, если бы синтаксис SQL мог принимать переменные, параметризованные, связанные с столбцом или имена таблиц. Но это не так. И это по дизайну. Вместо этого RDBMS предоставляет вам все инструменты, которые вам когда-либо понадобились, чтобы связывать ваши данные друг с другом. Используя его по назначению, вам никогда не придется прибегать к таким «динамическим» трюкам.

В вашем случае, должно быть одинconfig стола с mid колонки различать те строки, которые относятся к конкретному mid значению. Тогда запрос будет простым:

select * from `config` where mid='$mid' and cid='$cid' 

Это реляционный способ. Таким образом, R в СБД. Нет абсолютно никакой причины смешивать данные с метаданными. Если вы это сделаете, вы перемещаете проблему разрешения отношений на более высоких уровнях модели приложения.

И последнее: можно утверждать, что таблицы config_{mid} могут иметь сходную, но не идентичную структуру. Для этого есть решение: IS-A relations.

Сказав, что для вашей конкретной проблемы решение в соответствии с ответом Бармара сделало бы трюк.

+0

Сначала я думал о том, как использовать таблицу 'config', но поскольку для каждой« середины »существует произвольное количество« настроек », это на самом деле невозможно. –

+1

Помимо подхода IS-A я упомянул, что если структура не может быть классифицирована каким-либо полезным способом, вы все равно можете реализовать ее, используя таблицу пар ключ/значение: 'CONFIG (mid, cid, setting_name, setting_value)'. Но избегайте сурового числа таблиц; вы только делаете это хуже. – geomagas

+0

На самом деле, мне очень нравится эта идея, спасибо. Вы бы рекомендовали создать две таблицы, то есть 'setting_ids', которые имеют 3 столбца:' sid', 'mid',' setting_name' (так что каждый параметр можно определить здесь) и другую таблицу, в которой помещается каждый экземпляр параметра для каждого 'cid ', имеющие столбцы:' id', 'sid',' cid', 'setting_val'. Поэтому в первой таблице я мог бы иметь строку: 'sid = 1',' mid = bank', 'setting_name = sign', а затем в другой таблице есть строки с vals:' cid = 345', 'setting_val = £ '; 'cid = 24',' setting_val = $ '-> обе строки имеют' sid = 1'. –

Смежные вопросы