6

ピボットテーブルの作成方法に関するstackoverflowの投稿のほとんどを読みましたが、すべての投稿は、列に関する予備知識のある例を示しています。列が何であるかについての知識がない場合、どのようにクエリを作成しますか。ここにいくつかのサンプルデータがあります:

id       column       value       Row
1        age          13          1
2        height       55          1
3        fav number   NULL        1
4        siblings     4           1
5        age          55          2
6        height       54          2
7        fav number   12          2

私はこの出力を探しています:

row        age       height        fav number       siblings
1          13        55            NULL             4
2          55        54            12               NULL

ご覧のとおり、行2には兄弟のエントリがありません。クエリの時点では、列名は不明です。このクエリをどのように作成しますか。

4

2 に答える 2

2

期待どおりにMySQLまたはPostgreSQLでこれを実行できるかどうかは疑問ですが、データが非常に自由形式である場合に使用した代替手段があります。私たちのユースケースは「メニュー項目がアプリケーションに返す属性」であり、もちろんクエリではこれらの知識はありません。ただし、単純なピボットテーブルを作成することはできません。

できない理由は、PostgreSQLでは、返されるタプル構造が事前に定義されている必要があるためです。すべてのデータベースがこれを行うわけではありませんが(たとえば、Informixでは、異なる行が異なる構造を持つことができます!)、ほとんどのデータベースがこれを行います。

私たちのアプローチはPostgreSQLのみです。ただし、多少の調整を加えることで、MySQLに相当するものをどこかに見つけることができます。私たちがしたことは基本的にあなたのバージョンにあります:

select row, array_agg("column" || '=' || "value") from sample_data group by row;

これにより、次のような出力が生成されます。

1 {"age=3","height=55",null,"siblings=4"}
2 {"age=55","height=54","favorite_number=12"}

次の方法でNULLを取り除くこともできます。

select row, array_agg("column" || '=' || "value")
 WHERE value is not null
 GROUP BY row;

次に、次のようなものが得られます。

1 {"age=3","height=55","siblings=4"}
2 {"age=55","height=54","favorite_number=12"}

しかし、MySQLで同じことを行う方法はわかりません。

于 2012-09-01T01:31:55.920 に答える
2

必要なものを取得するために、凝ったSELECTクエリを作成する方法がわかりません。前処理を行う必要があります。


ある種のプログラム、アプリケーション、スクリプトなどからこのMySQLクエリを実行する必要があります。言語が何であるかはわかりませんが、PHPで行うことは次のとおりです。

/* $data is where our data is going to be stored in our desired format */
$data = array();
/* $columns is a list of all column names */
$columns = array();
/* $rows is a list of all row names (probably '1', '2', etc) */
$rows = array();

$result = mysql_query('SELECT column, value, row FROM TableName');
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
  /* if this row isn't in $data yet, add it */
  if (!array_key_exists($row['row'], $data) {
    $data[$row['row']] = array();
  }

  /* if this column isn't in $columns yet, add it */
  if (!in_array($row['column'], $columns)) {
    array_push($columns, $row['column']);
  }

  /* if this row isn't in $rows yet, add it */
  if (!in_array($row['row'], $rows)) {
    array_push($rows, $row['row']);
  }

  /* set the actual value in our multi-dimensional array $data */
  $data[$row['row']][$row['column']] = $row['value'];
}
/* free the result (php specific thing) */
mysql_free_result($result);

/* if we didn't set anything (row, column) pairs, set it to null in $data */
foreach ($rows as $r) {
  foreach ($columns as $c) {
    if (!array_key_exists($c, $data[$r])) {
      $data[$r][$c] = null;
    }
  }
}

これにより、すべてのデータがPHPの配列に必要な形式になります。


たとえば、上記で提供したサンプルデータに対してこのアルゴリズムを実行すると、次のことができるようになります。

echo $data['2']['age']; // $data['row']['column']

これは55を出力します。


または、データベースがリアルタイムで更新されていない場合(継続的にではなく、一度だけ再フォーマットしたいデータがたくさんある場合)、上記のスクリプトを拡張して、「CREATE TABLE」、「INSERT」を追加することもできます。 INTO "クエリは、基本的に、探している形式でテーブルを再作成します。

さらに、リアルタイムでデータを受信して​​いる場合でも、上記のスクリプトを記述できますが、処理時に元のテーブルから行を削除し、データが入力されるたびにスクリプトを実行するだけです。元のテーブル。

于 2012-08-31T20:41:07.670 に答える