困惑... MYSQL + JOIN + PAGINATION
Boggled... MYSQL + JOIN + PAGINATION
我花了太长时间试图自己想出一个好的解决方案来解决这个问题。还没有找到任何好的答案来提供帮助,尽管我已经尝试过从不同的答案中网格化解决方案,但没有成功。
Goal: Present a paginated Projects page containing data from multiple
tables.
我在单个 MYSQL 查询中使用多个连接,因为我想避免 PHP 循环中的 运行 查询。仅此一项就引入了 fetch_assoc 问题,由于查询产生的重复行,我不得不从 while(fetch_assoc)
循环构建自己的结果数组。但是,下一个问题是查询通过分页 class 运行,我用它来生成分页链接并获取查询数据,如 num_rows 等。
所以现在,我有一个显示我想要的数据的页面,但是分页 class 显示错误的行数和分页链接。不确定解决此问题的最佳方法是什么。希望从你们其中一位杰出的专家那里得到一些想法!
代码基本上是:
$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 个项目。所以分页 class 显示 7 num_rows(正确)但只有 4 个项目。
欢迎提出任何想法!
我可能会将其他表的子查询结果连接到自己列中的字符串值,并使用 php explode()
等进行解析,然后生成包含所有数据的单个项目行, 但我还没有做到。
提前感谢您的帮助!
我能想出的唯一解决方案是将子查询/连接的结果连接到主结果集中的单个列中。这使我无需修改分页就可以获得所需的结果 class.
请参阅此 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()
一样。最终,您最终会在单个 column/row 中得到格式化的结果字符串,您可以在其中使用 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。请参阅 this answer 解决该问题。我建议您积极主动并立即更改它,除非您绝对确定您的值永远不会超过 1024。
我花了太长时间试图自己想出一个好的解决方案来解决这个问题。还没有找到任何好的答案来提供帮助,尽管我已经尝试过从不同的答案中网格化解决方案,但没有成功。
Goal: Present a paginated Projects page containing data from multiple tables.
我在单个 MYSQL 查询中使用多个连接,因为我想避免 PHP 循环中的 运行 查询。仅此一项就引入了 fetch_assoc 问题,由于查询产生的重复行,我不得不从 while(fetch_assoc)
循环构建自己的结果数组。但是,下一个问题是查询通过分页 class 运行,我用它来生成分页链接并获取查询数据,如 num_rows 等。
所以现在,我有一个显示我想要的数据的页面,但是分页 class 显示错误的行数和分页链接。不确定解决此问题的最佳方法是什么。希望从你们其中一位杰出的专家那里得到一些想法!
代码基本上是:
$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 个项目。所以分页 class 显示 7 num_rows(正确)但只有 4 个项目。
欢迎提出任何想法!
我可能会将其他表的子查询结果连接到自己列中的字符串值,并使用 php explode()
等进行解析,然后生成包含所有数据的单个项目行, 但我还没有做到。
提前感谢您的帮助!
我能想出的唯一解决方案是将子查询/连接的结果连接到主结果集中的单个列中。这使我无需修改分页就可以获得所需的结果 class.
请参阅此 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()
一样。最终,您最终会在单个 column/row 中得到格式化的结果字符串,您可以在其中使用 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。请参阅 this answer 解决该问题。我建议您积极主动并立即更改它,除非您绝对确定您的值永远不会超过 1024。