合并具有不同列的表的搜索结果,并按日期排序


merge search results of tables with different colums and sort by date

我试图用一个输出构建三个不同日志表的搜索结果。这个输出必须按"时间"排序,并在foreach循环中进行响应。

  1. id |记录id |用户id |时间|扇区|信息

  2. id|user_id|ip|time|path|info|message|level

  3. id | req_id |用户|时间|信息|类型| ip

这三个结果都是不同的,很难进行比较。。。

问题是,在哪里以及如何合并结果。。。我不认为我只需要一个查询就可以处理这个问题,或者?JOIN(没有引用)和UNION(不同列数)可能是错误的选择?

如果没有其他选项,我可以进行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'); 

一个可能的解决方案是使用UNION ALLCONCAT_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

样本输出:

|源|ID|ID2|TIME|DETAILS|-------------------------------------------------------------------------------------------------------------------|1|11|11|2013-06-30 16:00:00|12|sector1|信息详细信息||2|12|13|2013-06-30 15:00:00|10.10.10.1|/your/path/some/where|信息详细信息|消息详细信息|level1||3 | 13 | 1024 | 2013-06-30 12:00:00 | user1 |信息详细信息|类型信息| 10.10.10.2|

这里是SQLFiddledmeo

只要"拉伸"不平衡列的结果,就可以使用并集,例如

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个不同的查询。在某种程度上,为了再次分离出相关数据,您必须在客户端中进行额外的处理,这超过了启动单个联合查询的微小效率收益。