Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.128.199.88] |
|
Данный раздел предназначается исключительно для обсуждения вопросов использования языка запросов SQL. Обсуждение общих вопросов, связанных с тематикой баз данных - обсуждаем в разделе "Базы данных: общие вопросы". Убедительная просьба - соблюдать "Правила форума" и не пренебрегать "Правильным оформлением своих тем". Прежде, чем создавать тему, имеет смысл заглянуть в раздел "Базы данных: FAQ", возможно там уже есть ответ. |
Сообщ.
#1
,
|
|
|
Добрый день.
Я немного упрощу описание проблемы и заменю названия для наглядности. У меня два сервера, на первом хранятся МУЖИКИ с id-шниками. На втором БАБЫ тоже с id-шниками. На первом сервере, в таблицу с МУЖИКАМИ первого сервера добавил ручками столбец "WomanId" и забил туда по нужным мне соответствиям(ну скажем это жены ихние) id-шники БАБ со второго сервера. Получилось что-то типа такого: ManId____ManName_______WomanId 1025_____Игорь_________541 1021_____Борис_________645 Мне нужно получить на первом сервере данные в таком виде: Имя мужика/Имя бабы Как я делал: $result1 = mysqli_query($server1, 'SELECT ManId, ManName, WomanId FROM bd1.Man;'); while ($row1 = mysqli_fetch_array($result1)) { $result2 = mysqli_query($server2, 'SELECT WomanName FROM bd2.Woman WHERE WomanId ='.$row1[2].';'); while ($row2 = mysqli_fetch_array($result2)) { echo $row1[1]." ".$row2[0]."</br>"; } } Получаю нужные мне "Имя мужика/Имя бабы" Но, мужиков у меня больше 1000, в итоге в цикле отправляется 1000+ запросов к второму серверу с бабами, это работает, но очень медленно. На mssql получал список баб одним запросом: Формировал xml: <row id = "1025">541</row> <row id = "1021">645</row> и отправлял запрос к второму серверу "declare @xml xml SET @xml='<row id = "1025">541</row> <row id = "1021">645</row>... Т.е. я прописывал в xml соответствия мужик_id/баба_id и второй сервер мне возвращал данные в таком виде ManId(который я же ему и отправлял в xml)/и имя бабы 1025/Света 1021/Люся После чего, слинковать баб к мужикам по id из запроса плевое дело. Можно как нибудь так же, одним запросом на mysql сделать?(Модифицировать базы нельзя only read, настраивать базы, прописывать линки нельзя, only php и only read) Ну или может еще какие варианты есть? Спасибо. |
Сообщ.
#2
,
|
|
|
На первый сервер шлёшь запрос
SELECT ManId, ManName, WomanId FROM bd1.Man; Полученные данные валишь в массив. Все полученные WomanId собираешь в одну переменную, разделяя значения запятыми, и шлёшь на второй сервер запрос SELECT WomanId, WomanName FROM bd2.Woman WHERE WomanId IN (WomanId-1, WomanId-2, ... , WomanId-N); Полученные данные валишь во второй массив. Затем объединяешь массивы в один по равенству поля WomanId. Всё. PS. Возможная ошибка - попытка вставить переменную со списком как параметр. В этом случае список будет обрамлён кавычками и воспринят как один длинный литерал, а не список. |
Сообщ.
#3
,
|
|
|
Цитата Akina @ Затем объединяешь массивы в один по равенству поля WomanId. А как объеденить то?)) Тут сортировка нужна сравнивать ID то что пришло от баб и те бабские ID которые у мужиков были. Потому что приходит ответ не сортированный ну никак, да и даже если бы был сортированный, у меня мужиков к примеру тысяча, а ID баб подбиты 900 к примеру - так что в цикле тоже не рассортируешь - нужен алгоритм посложнее. А сортировка, поверь, по скорости практически тоже самое, что юзать так, как я написал. Ну мб чуть быстрее. Делал я так. Не варик. Варик - это получить WomanID вместе с отправляемыми ManID - тогда можно сразу найти нужный тип/массив по ManID и записать туда WomanName. Т.е. я отправляю на бабский сервер xml с мужскими и женскими ID, джойню с таблицей Woman и получаю ответ из бд и из xml. Из xml ManID, из бд WomanName. Тогда мне ответ приходит такой: ManID|WomanName, мне не надо сортировать, я просто ложу WomanName по ManID. Вот что я бы хотел, но у меня проблема с синтаксисом - не могу переписать запрос с mssql на mysql. Вот то, что я пытался сваять из рабочего mssql запроса и нужного мне mysql. Но ошибка, как исправить не знаю... $qer формирую когда получаю ответ от первого сервера. Примерно так: $qer.=('<row id = "'.$id_one[$row[0]].'">'.$id_two[$row[0]].'</row>'); DECLARE xml TEXT; SET xml='<rows>".$qer."</rows>'; SELECT Art.SortKey, t1.PRICE, t2.VALUE FROM (select b.value('@id' , 'int') [SortKey], b.value('.' , 'varchar(50)') [ArtNo] FROM @xml.nodes('/rows/row') a(b) )as Art LEFT JOIN b_catalog_price AS t1 ON t1.PRODUCT_ID = Art.ArtNo LEFT JOIN b_iblock_element_property AS t2 ON t2.IBLOCK_ELEMENT_ID = t1.PRODUCT_ID AND t2.IBLOCK_PROPERTY_ID = 47 |
Сообщ.
#4
,
|
|
|
Цитата Rzonex @ А как объеденить то? Понятия не имею - я в ПХП ни ухом ни рылом... но вроде как там функций для обработки массивов море, неужто не найдётся объединение по ключу? Цитата Rzonex @ А сортировка, поверь, по скорости практически тоже самое, что юзать так, как я написал. Фигню говоришь. Добавь в запрос нужный ORDER BY, и получишь результат уже сортированным. И поверь, это будет гораздо быстрее, чем сортирить на клиенте (кстати, уж сортирить массивы ПХП сто пудов умеет). |
Сообщ.
#5
,
|
|
|
Цитата Akina @ Фигню говоришь. Я имел в виду сортировку в самом php. У меня объявлен тип, в котором я храню всю нужную информацию. Идентификатором этого типа является ManID. Вот пришел мне запрос с голыми WomanName, ну и WomanID. А мне каждую бабу эту нужно записать в php тип. Но куда? А туда где WomanID из запроса будет равен WomanID типа. Как это сделать? Самое простое - создать еще тип, добавить в него все поля из запроса, и крутить сравнение в цикле - если совпало, записывать один тип в другой и удалять тот который из запроса был создан. В итоге получаем простейшую сортировку. А без этого, рассортировать запрос в тип я не могу. И такие костыли я уже делал. Оно плохо работает, оно мне не по душе, оно мне не нравится. А мне нравится послать xml к бабам и получить в лтвете баб и id мужиков, чтобы я сразу мог результат в php записать в нужный мне тип. |
Сообщ.
#6
,
|
|
|
Цитата Мне нужно получить на первом сервере данные в таком виде: Имя мужика/Имя бабы вот тебе костыль вариант 1 $result1 = mysqli_query($server1, 'SELECT ManId, ManName, WomanId FROM bd1.Man;'); $result2 = mysqli_query($server2, 'SELECT WomanId, WomanName FROM bd2.Woman;'); for ($res1 = array(); $tmp = $result1->fetch_array(MYSQLI_ASSOC);) $res1[] = $tmp; for ($res2 = array(); $tmp = $result2->fetch_array(MYSQLI_ASSOC);) $res2[] = $tmp; foreach($res1 as $man){ foreach($res2 as $woman){ if ($man['WomanId'] == $woman['WomanId']) { echo $man['ManName']." ".$woman['WomanName']."</br>"; break; } } } вот тебе костыль вариант 2 $result1 = mysqli_query($server1, 'SELECT ManId, ManName, WomanId FROM bd1.Man;'); $result2 = mysqli_query($server2, 'SELECT WomanId, WomanName FROM bd2.Woman;'); $womans = array(); while ($row2 = mysqli_fetch_array($result2)) { $womans[$row2['WomanId']] = $row2['WomanName']; } while ($row1 = mysqli_fetch_array($result1)) { echo $row1['ManName']." ".$womans[$row1['WomanId']]."</br>"; } |
Сообщ.
#7
,
|
|
|
Цитата Rzonex @ Я имел в виду сортировку в самом php. ЗАЧЕМ? Оставь решение задачи сортировки тому, кто умеет это делать лучше - серверу MySQL. |
Сообщ.
#8
,
|
|
|
Цитата Akina @ Так я этого и добиваюсь))) Но что бы мне не делать сортировку в php - мне нужны данные от мускула в виде ManId/WomanName Цитата Gonarh @ вот тебе костыль вариант 1 У меня на обоих сайтах овер 1000 записей. Тут у тебя два вложенных цикла, это миллион итераций. Это будет работать, но это костыль. Добавлю, что у меня не два сайта а 4. Это при 1000 записей 4 милиона итераций, при 2000 будет уже 16 лямов, рост в геом. прогрессии. Если оптимизировать, то нужно делать правильно. А ваш вариант это костыль, уж простите. Ну разве нельзя отправить на второй сервер запрос с xml с ManID|WomanId? Чтобы он вернул ManId|WomanName??? |
Сообщ.
#9
,
|
|
|
Второй вариант - двухпроходный цикл
Добавлено Цитата Rzonex @ Это при 1000 записей 4 милиона итераций, при 2000 будет уже 16 лямов, рост в геом. прогрессии. Не будет там 16 млн итераций. Добавлено Цитата Rzonex @ Ну разве нельзя отправить на второй сервер запрос с xml с ManID|WomanId? Отправить то ты можешь, только там ManID нахер не нужон. |
Сообщ.
#10
,
|
|
|
Цитата Rzonex @ Ну разве нельзя отправить на второй сервер запрос Можно. Цитата Rzonex @ с xml с ManID|WomanId? Можно, но бессмысленно. MySQL не понимает запросов в XML-формате. Озвучьте версию второго MySQL. Можно крупно - 5 или 8? |
Сообщ.
#11
,
|
|
|
Цитата Gonarh @ Отправить то ты можешь, только там ManID нахер не нужон. Нет, он там нужон. А для чего? Чтобы он вернулся вместе с WomanName, чтобы мне не сортировать в php потом, не делать вложенных циклов. Я так делал на mssql это работало очень быстро. Цитата Gonarh @ Не будет там 16 млн итераций. Да будет меньше, 16 млн, это если искомая запись всегда будет последней в цикле. Я не хочу так делать, у меня скоро пять сайтов будет, а может еще больше. Нужен оптимизированный вариант... |
Сообщ.
#12
,
|
|
|
Цитата Rzonex @ Модифицировать базы нельзя only read, настраивать базы, прописывать линки нельзя, only php и only read Заведите свой, третий, MySQL-сервер, и с него аттачьтесь к первым двум. Обойдётесь одним простым запросом. The FEDERATED Storage Engine |
Сообщ.
#13
,
|
|
|
Цитата Akina @ Озвучьте версию второго MySQL. Можно крупно - 5 или 8? У меня скоро пять сайтов будет. Везде разные версии... Цитата Akina @ Заведите свой, третий, MySQL-сервер, и с него аттачьтесь к первым двум. Обойдётесь одним простым запросом. Не могу. На сервере, где запускаю скрипт отключен удаленный доступ к бд, точнее он есть но через ssh туннель. Цитата Akina @ Можно, но бессмысленно. MySQL не понимает запросов в XML-формате. Очень печально. Может все-таки можно как-нибудь отправить запрос с ManID и соответствующими им WomanID? Чтобы в ответе сохранялся порядок ManID/WomanName? Это все что нужно, это будет работать очень быстро, я так делал... |
Сообщ.
#14
,
|
|||||||||||||||||||||
|
Возможное решение-костыль.
Делаем первый запрос на первый сервер. SELECT ManId, ManName, WomanId FROM bd1.Man; Получаем, к примеру
На основании этих данных формируем запрос на второй сервер, который выглядит так: SELECT t1.ManName, bd2.WomanName FROM ( SELECT 'Петя' ManName, 111 WomanId UNION ALL SELECT 'Коля', 112 UNION ALL SELECT 'Вася', 113 ) AS t1 LEFT JOIN bd2.Woman ON t1.WomanId = bd2.WomanId; и получаем в ответ
Последний NULL означает, что Вася ещё пока неженатый. |
Сообщ.
#15
,
|
|
|
Цитата Akina @ Возможное решение-костыль. Не думаю что это костыль, если оно будет работать так, как я думаю, то это оптимальный вариант. Спасибо сейчас затестим. Это песня, это сказка Работает очень быстро и никакой это не костыль, а имхо оптимальное решение. Спасибо большое Akina! |
Сообщ.
#16
,
|
|
|
А если сервер поддерживает Federated таблицы, то все намного проще...
|