使用一个查询创建汇总结果

发布于 2024-09-14 22:06:31 字数 1798 浏览 5 评论 0原文

我有一个具有以下格式的表格。

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有多个characteristic_name/value对。我想使用 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  | ...          |
+----------------------+------------------+------+-----+---------+--------------+

只需要一个查询就可以实现吗?

谢谢, -彼得

I have a table with the following format.

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    |                |
+----------------------+------------------+------+-----+---------+----------------+

each uut_sn has multiple characteristic_name/value pairs. I want to use MySQL to generate a table

+----------------------+-------------+-------------+-------------+--------------+
| 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  | ...          |
+----------------------+------------------+------+-----+---------+--------------+

Is this possible with just one query?

Thanks,
-peter

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

请别遗忘我 2024-09-21 22:06:32

您正在使用 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。

You're using the EAV antipattern. There's no way to automatically generate the pivot table you describe, without hardcoding the characteristics you want to include. As @OMG Ponies mentions, you need to use dynamic SQL to general the query in a custom fashion for the set of characteristics you want to include in the result.

Instead, I recommend you fetch the characteristics one per row, as they are stored in the database, and if you want an application object to represent a single UUT with all its characteristics, you write code to loop over the rows as you fetch them in your application, collecting them into objects.

For example in 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"];
}

This has a few advantages over the solution of hardcoding characteristic names in your query:

  • This solution takes only one SQL query instead of two.
  • No complex code is needed to build your dynamic SQL query.
  • If you forget one of the characteristics, this solution automatically finds it anyway.
  • GROUP BY in MySQL is often slow, and this avoids the GROUP BY.
愿与i 2024-09-21 22:06:31

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

  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 语法称为预准备语句。它需要两个查询 - 第一个查询获取 characteristic_name 值的列表,因此您可以将适当的字符串连接到 CASE 表达式中,就像您在我的示例中看到的最终查询一样。

This is a standard pivot query:

  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

To make it dynamic, you need to use MySQL's dynamic SQL syntax called Prepared Statements. It requires two queries - the first gets a list of the characteristic_name values, so you can concatenate the appropriate string into the CASE expressions like you see in my example as the ultimate query.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文