MySQL动态交叉表

时间:2012-01-23 20:04:58

标签: mysql aggregate-functions pivot-table crosstab

我有一张这样的表:

way     stop    time
1       1       00:55
1       2       01:01
1       3       01:07
2       2       01:41
2       3       01:47
2       5       01:49
3       1       04:00
3       2       04:06
3       3       04:12

我想要一张这样的表:

stop    way_1   way_2   way_3   (way_n)
1       00:55           04:00
2       01:01   01:41   04:06
3       01:07   01:47   04:12
5               01:49

网上有很多关于MySQL交叉表(数据透视表)的解决方案,但如果我不知道有多少“方式”,我怎么能这样做呢? 感谢

1 个答案:

答案 0 :(得分:4)

在准备查询时,必须修复列的数量和名称。这就是SQL的工作方式。

所以你有两种选择来解决这个问题。两种选择都涉及编写应用程序代码:

(1)查询way的不同值,然后编写代码以使用它们构建数据透视查询,在SELECT列表中追加尽可能多的列作为不同的数量值。

foreach ($pdo->query("SELECT DISTINCT `way` FROM `MyTable`") as $row) {
  $way = (int) $row["way"];
  $way_array[] = "MAX(IF(`way`=$way, `time`)) AS way_$way";
}
$pivotsql = "SELECT stop, " . join(", ", $way_array) .
   "FROM `MyTable` GROUP BY `stop`";

现在您可以运行新查询,它的列数与不同way值的数量相同。

$pivotstmt = $pdo->query($sql);

(2)逐行查询数据,因为它在数据库中构建,然后在显示数据之前编写代码以转入列。

$stoparray = array();
foreach ($pdo->query("SELECT * FROM `MyTable`") as $row) {
  $stopkey = $row["stop"];
  if (!array_key_exists($stopkey, $stoparray)) {
    $stoparray[$stopkey] = array("stop"=>$stopkey);
  }
  $waykey = "way_" . $row["way"];
  $stoparray[$stopkey][$waykey] = $row["time"];
}

现在你有一个数组数组,看起来就像你运行了一个数据透视查询一样,但你运行的实际SQL要简单得多。您将查询结果后处理为一组不同的数组。