2015-02-21 3 views
1

Я слишком долго пытался найти подходящее решение этой проблемы самостоятельно. Не нашли никаких хороших ответов, чтобы помочь, хотя я и попытался объединить решения из разных ответов без везения.Boggled ... MYSQL + JOIN + PAGINATION

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

Я использую несколько объединений в одном запросе MYSQL, потому что я хотел избежать выполнения запросов в петле PHP. Это само по себе ввело проблему fetch_assoc, где мне пришлось создать собственный массив результатов из цикла while(fetch_assoc) из-за повторяющихся строк, полученных в результате запроса. Однако следующая проблема заключается в том, что запрос выполняется через класс pagination, который я использую для создания ссылок на страницы и получения данных запроса, таких как 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 проектов. Таким образом, класс pagination показывает 7 num_rows (по праву), но есть только 4 проекта.

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

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

Заранее благодарю вас за помощь!

+0

Как ваш класс пейджера извлекает количество строк? Не считал бы (отличная project_id) помощь? – pvytykac

+0

Он использует '$ res = $ conn-> query ($ sql)' и '$ res-> num_rows;', и класс обычно используется во всем проекте. Именно на этой странице проектов это мешает. – Chris

ответ

0

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

См пример каскадных результатов в этом 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); 
     } 
    } 
} 

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

EDIT: В то время как это решение работает для меня очень хорошо, я столкнулся с проблемой с пределом длины по умолчанию для GROUP_CONCAT, который равен 1024. Любое значение, которое было более 1024, было сокращено до 1024. См. this answer. разрешите это. Я бы посоветовал вам быть активным и изменить его сейчас, если вы не уверены, что ваши значения никогда не будут длиннее 1024.