繁体   English   中英

MySQL - 根据另一列的值将行值透视为列组

[英]MySQL - Pivot row values into column groups based on value of another column

我正在尝试建立一个产品比较页面。 我有以下 MySQL 表。 将 item_id 列视为 product_id

+---------+------------------+-------------------------+
| item_id | field_name       | field_value             |
+---------+------------------+-------------------------+
|       1 | Operating System | Windows 7               |
|       1 | Processor        | Core i3                 |
|       1 | Brand            | HP                      |
|       2 | Operating System | Windows 10              |
|       2 | Processor        | Core i7                 |
|       2 | Brand            | Dell                    |
+---------+------------------+-------------------------+

我试图得到一个结果,我可以将 item1 (item_id=1) 和 item2 (item_id=2) 的品牌、操作系统和处理器的值作为单行并排比较。 要比较的产品数量(即:- 列)最少为两个,最多为四个。

我已经看到这里找到的答案 -> MySQL 将行转换为动态列数,但不同之处在于我的动态列基于 item_id 的值,而 field_name 值将用于一列。 field_value 的值将根据 item_id 添加到动态列中。 根据答案,我尝试了以下基于案例的语句,但它创建了一些不必要的空值

SELECT 
    field_name,
    CASE
        WHEN price_fid = 1 THEN field_value
    END AS item1,
    CASE
        WHEN price_fid = 2 THEN field_value
    END AS item2
FROM
    custom_fields;

结果:

+------------------+-----------+-------------------------+
| field_name       | item1     | item2                   |
+------------------+-----------+-------------------------+
| Operating System | Windows 7 | NULL                    |
| Processor        | Core i3   | NULL                    |
| Brand            | HP        | NULL                    |
| Operating System | NULL      | Windows 10              |
| Processor        | NULL      | Core i7                 |
| Brand            | NULL      | Dell                    |
+------------------+-----------+-------------------------+

如您所见,品牌、操作系统和处理器在 field_name 列中出现了两次,并且 item1 和 item2 都为空值。 我还查看了以下答案 -> 基于 SQL 中分组列的列上的枢轴值,但仍然存在空值或重复字段名称的问题。

我想要得到的是单行中两个项目(产品)的价值。 这是我正在寻找的结果。

+------------------+-----------+------------+
| field_name       | item1     | item2      |
+------------------+-----------+------------+
| Brand            | HP        | Dell       |
| Operating System | Windows 7 | Windows 10 |
| Processor        | Core i3   | Core i7    |
+------------------+-----------+------------+

是否可以运行 MySQL 查询来获得上述输出? 如果是这样,有没有办法轻松地向其中添加第三个和第四个 item_id(即:- 列)。 我正在寻找基于案例或其他类型的查询,我可以轻松实现从 PHP 调用。 如果无法通过标准的 mysql 查询,我仍然不介意 t-sql 语句或过程。 谢谢

您可以group by field_name并使用条件聚合:

SELECT field_name,
       MAX(CASE WHEN item_id = 1 THEN field_value END) item1,
       MAX(CASE WHEN item_id = 2 THEN field_value END) item2,
       MAX(CASE WHEN item_id = 3 THEN field_value END) item3 -- for a 3d column
       .....................................................
FROM custom_fields
GROUP BY field_name

请参阅演示

一个更加动态的方法是。

可以在第一个sql语句中添加A WHERE item_id IN (1,2,3,4) ,选择你想看的item_ids

 CREATE TABLE custom_fields ( `item_id` INTEGER, `field_name` VARCHAR(16), `field_value` VARCHAR(10) ); INSERT INTO custom_fields (`item_id`, `field_name`, `field_value`) VALUES ('1', 'Operating System', 'Windows 7'), ('1', 'Processor', 'Core i3'), ('1', 'Brand', 'HP'), ('2', 'Operating System', 'Windows 10'), ('2', 'Processor', 'Core i7'), ('2', 'Brand', 'Dell');
 SET @sql = NULL; SELECT GROUP_CONCAT(DISTINCT CONCAT( 'MAX(case when item_id = ''', item_id, ''' then field_value ELSE NULL END) AS item', item_id ) ) INTO @sql from custom_fields; SET @sql = CONCAT('SELECT field_name, ', @sql, ' FROM custom_fields group by field_name'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
\n\n字段名称 | 项目 1 | 项目 2     \n :--------------- |  :-------- |  :---------\n操作系统 | 视窗 7 | 视窗 10\n处理器 | 酷睿 i3 | 酷睿i7   \n品牌 | 惠普 | 戴尔      \n

db<> 在这里摆弄

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM