我正在尝试使用一个输出构建三个差异日志表的搜索结果。此输出必须按“时间”排序,并在foreach循环中回显。
表
id | record-id | user_id |时间|部门|信息
表
id | user_id | ip |时间|路径|信息|消息|水平
表
id | req_id |用户|时间|信息|类型| IP
这三个结果会有所不同,几乎无法比较......
问题是,在哪里以及如何合并结果...我不认为我只用一个查询来处理这个问题,或者? JOIN(没有参考)和UNION(不同的colums数)可能是错误的选择?
如果没有其他选项,我可以进行3次查询并合并结果数组
function cmp($a, $b) {
if ($a['time'] == $b['time']) {
return 0;
}
return ($a['time'] < $b['time']) ? -1 : 1;
}
$new_arr = array_merge($result1, $result2, $result3);
uasort($new_arr, 'cmp');
答案 0 :(得分:1)
只要您“拉伸”不平衡列的结果,就可以使用联合,例如
SELECT 'table1' AS source, record_id, user_id, time, sector, path
UNION ALL
SELECT 'table2', user_id, null, null, ip, etc....
UNION ALL
SELECT 'table3', null, req_id, null, null, ip, etc...
基本上对于三个表之间常见的任何字段,或者至少是类型兼容的字段,您可以在该字段的结果中使用特定列。对于一个表中不匹配/类型不兼容的字段,只需在其他查询中选择NULL
作为“匹配”值。
但是,这会使您的客户端逻辑变得更加复杂,因此您最好只是咬住子弹并运行3个不同的查询。在某些时候,在客户端中必须进行额外的处理以再次分离出相关数据时,触发单个联合查询的次要效率提升超过了。
答案 1 :(得分:1)
一种可能的解决方案是使用UNION ALL
和CONCAT_WS()
将结果集统一为固定数量的列(下例中为5)。然后迭代结果集时,php中的explode()
details
列值。
SELECT 1 source, id, record_id id2, time, CONCAT_WS('|', user_id, sector, info) details
FROM table1
UNION ALL
SELECT 2, id, user_id, time, CONCAT_WS('|', ip, path, info, message, level)
FROM table2
UNION ALL
SELECT 3, id, req_id, time, CONCAT_WS('|', user, info, type, ip)
FROM table3
ORDER BY time DESC, source, id, id2
示例输出:
| SOURCE | ID | ID2 | TIME | DETAILS | ------------------------------------------------------------------------------------------------------------------- | 1 | 11 | 111 | 2013-06-30 16:00:00 | 12|sector1|info details | | 2 | 12 | 13 | 2013-06-30 15:00:00 | 10.10.10.1|/your/path/some/where|info details|message details|level1 | | 3 | 13 | 1024 | 2013-06-30 12:00:00 | user1|info details|type info|10.10.10.2 |
这是 SQLFiddle dmeo