1

我有一个格式如下的表格。

mysql> describe unit_characteristics;
+----------------------+------------------+------+-----+---------+----------------+
| Field                | Type             | Null | Key | Default | Extra          |
+----------------------+------------------+------+-----+---------+----------------+
| id                   | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| uut_id               | int(10) unsigned | NO   | PRI | NULL    |                |
| uut_sn               | varchar(45)      | NO   |     | NULL    |                |
| characteristic_name  | varchar(80)      | NO   | PRI | NULL    |                |
| characteristic_value | text             | NO   |     | NULL    |                |
| creation_time        | datetime         | NO   |     | NULL    |                |
| last_modified_time   | datetime         | NO   |     | NULL    |                |
+----------------------+------------------+------+-----+---------+----------------+

每个 uut_sn 都有多个特征名称/值对。我想用 MySQL 生成表

+----------------------+-------------+-------------+-------------+--------------+
| uut_sn | char_name_1 | char_name_2 | char_name_3 | char_name_4 | ...          |
+----------------------+-------------+-------------+-------------+--------------+
| 00000  | char_val_1  | char_val_2  | char_val_3  | char_val_4  | ...          | 
| 00001  | char_val_1  | char_val_2  | char_val_3  | char_val_4  | ...          |
| 00002  | char_val_1  | char_val_2  | char_val_3  | char_val_4  | ...          |
| .....  | char_val_1  | char_val_2  | char_val_3  | char_val_4  | ...          |
+----------------------+------------------+------+-----+---------+--------------+

这可能只需要一个查询吗?

谢谢,-彼得

4

2 回答 2

3

这是一个标准的数据透视查询:

  SELECT uc.uut_sn,
         MAX(CASE 
               WHEN uc.characteristic_name = 'char_name_1' THEN uc.characteristic_value 
               ELSE NULL 
             END) AS char_name_1,
         MAX(CASE 
               WHEN uc.characteristic_name = 'char_name_2' THEN uc.characteristic_value 
               ELSE NULL 
             END) AS char_name_2,
         MAX(CASE 
               WHEN uc.characteristic_name = 'char_name_3' THEN uc.characteristic_value 
               ELSE NULL 
             END) AS char_name_3,
    FROM unit_characteristics uc
GROUP BY uc.uut_sn

要使其动态化,您需要使用MySQL 的动态 SQL 语法,称为 Prepared Statements。它需要两个查询 - 第一个获取characteristic_name值列表,因此您可以将适当的字符串连接到 CASE 表达式中,就像您在我的示例中看到的那样作为最终查询。

于 2010-08-18T18:24:06.147 回答
1

您正在使用 EAV 反模式。如果不对您想要包含的特征进行硬编码,就无法自动生成您描述的数据透视表。正如@OMG Ponies 所提到的,您需要使用动态 SQL 以自定义方式对要包含在结果中的特征集进行通用查询。

相反,我建议您每行获取一个特征,因为它们存储在数据库中,如果您希望应用程序对象表示具有所有特征的单个 UUT,您可以编写代码以在获取行时循环它们您的应用程序,将它们收集到对象中。

例如在 PHP 中:

$sql = "SELECT uut_sn, characteristic_name, characteristic_value 
        FROM unit_characteristics";
$stmt = $pdo->query($sql);

$objects = array();
while ($row = $stmt->fetch()) {
  if (!isset($objects[ $row["uut_sn"] ])) {
      $object[ $row["uut_sn"] ] = new Uut();
  }
  $objects[ $row["uut_sn"] ]->$row["characteristic_name"] 
                            = $row["characterstic_value"];
}

与在查询中硬编码特征名称的解决方案相比,这有一些优势:

  • 这个解决方案只需要一个 SQL 查询而不是两个。
  • 构建动态 SQL 查询不需要复杂的代码。
  • 如果您忘记了其中一个特征,该解决方案无论如何都会自动找到它。
  • MySQL 中的 GROUP BY 通常很慢,这避免了 GROUP BY。
于 2010-08-18T18:29:16.740 回答