Ошеломленный … MYSQL + JOIN + PAGINATION

Я потратил слишком много времени, пытаясь найти хорошее решение этой проблемы самостоятельно. Не нашли хороших ответов, чтобы помочь, хотя я безуспешно пытался найти решения из разных ответов.

Цель: представить страницу проектов с разбивкой по страницам, содержащую данные из нескольких
столы.

Я использую несколько объединений в одном запросе MYSQL, потому что я хотел избежать выполнения запросов в цикле PHP. Уже одно это привело к проблеме fetch_assoc, когда мне пришлось создать собственный массив результатов из while(fetch_assoc) цикл из-за повторяющихся строк в результате запроса. Однако следующая проблема заключается в том, что запрос выполняется через класс разбиения на страницы, который я использую для генерации ссылок на страницы и получения данных запроса, таких как num_rows и тому подобное.

Итак, сейчас у меня есть страница, показывающая нужные мне данные, но класс разбивки на страницы показывает мне неправильное количество строк и ссылок на страницы. Не уверен, что лучший способ обойти эту проблему. Надеемся получить некоторые идеи от одного из вас, блестящих экспертов!

Код в основном:

$sql = "...."
$projects = new pager($sql)

echo $projects->num_rows

while($projects->fetch_assoc){
build new array from data
$project_array[][][]
}

foreach($project_array){
display data from all tables...
}

$projects->showPageLinks

это SQLFiddle предоставляет пример данных, которые я получаю:

Обратите внимание, что есть 7 строк результатов, но только для 4 проектов. Таким образом, класс разбиения на страницы показывает 7 num_rows (по праву), но есть только 4 проекта.

Любые идеи приветствуются!

Хотя, возможно, я объединяю результаты подзапроса из других таблиц в строковые значения в собственных столбцах и анализирую их с помощью php explode() и тому подобное, которое затем получило бы отдельные строки проекта со всеми данными, но я пока не смог этого сделать.

Заранее спасибо за вашу помощь!

1

Решение

Единственное решение, которое мне удалось найти, — объединить результаты подзапросов / объединений в отдельные столбцы в основном наборе результатов. Это позволяет мне получать результаты, которые мне нужны, без необходимости изменять класс нумерации страниц.

Смотрите пример связанных результатов в этом SQLFiddle

Пример запроса:

SELECT p.id pid, p.name pname, c.name cname,
GROUP_CONCAT(DISTINCT CONCAT_WS('|',w.hours,w.notes,t.name) SEPARATOR ';') as works

FROM projects p
LEFT JOIN (SELECT * FROM clients) AS c ON c.id=p.client_id
LEFT JOIN (SELECT * FROM work) AS w ON w.project_id=p.id
LEFT JOIN (SELECT * FROM tools) AS t ON t.id=w.tool_id
GROUP BY p.id

GROUP_CONCAT(DISTINCT ... это то, что объединяет отдельные строки из объединенных результатов, и CONCAT_WS('',col,col,..) объединяет отдельные столбцы результатов. Оба позволяют вам использовать разделители, которые вы определяете, так же, как php implode() было бы. В конечном итоге вы получаете отформатированную строку результатов в одном столбце / строке, в которой вы можете использовать php для explode() строки, а затем их столбцы.

Теперь я получаю правильное количество результатов и просто разбиваю строки и поля с помощью определенных разделителей.

Пример кода:

$wkeys = array('hours','notes','toolname'); // to use as array key (column name)

while($r=$projects->fetch_assoc()){
if(strpos($r['works'],';')!==false){
$wrows = explode(";",$r['works']); // individual rows

foreach($wrows as $k=>$v) {
$wv = explode("|",$v); // individual col=val pairs
$works[] = array_combine($wkeys,$wv);
}
}
}

Надеюсь, что это помогает кому-то еще, кто может столкнуться с той же ситуацией.

РЕДАКТИРОВАТЬ: Хотя это решение работает довольно хорошо для меня, я столкнулся с проблемой с ограничением длины по умолчанию для GROUP_CONCAT 1024. Любое значение, превышающее 1024, было сокращено до 1024. См. этот ответ чтобы решить это. Я бы посоветовал вам проявить инициативу и изменить ее сейчас, если только вы не уверены, что ваши значения никогда не будут больше 1024.

0

Другие решения

Других решений пока нет …