将逗号分隔的值从结果中的一列拆分为两行。 MySQL的

时间:2012-06-19 12:02:55

标签: mysql

的MySQL。两列,相同的表。
第1列有product_id
第2列有category_ids(有时2个类别,因此看起来像23,43)

如果有超过1个category_id与product_id相关联,如何编写查询以返回product_id,category_ids列表,并使用单独的行。


表格

product_id | category_ids 
100        | 200,300
101        | 201

查询结果:不尝试修改表格

100 | 200
100 | 300
101 | 201


编辑:(注意)我实际上并不想操纵桌子。只是在PHP中进行查询,所以我可以根据需要使用数据。

1 个答案:

答案 0 :(得分:1)

你的数据库表实现看起来很糟糕,但是在你的情况下你需要的是GROUP_CONCAT的反向函数,但不幸的是它在MySQL中不存在。

您有两个可行的解决方案:

  1. 更改存储数据的方式(允许在product_id字段上复制,并为不同的product_id添加相同category_id的多条记录
  2. 在您的应用程序中操作查询结果(您在问题中提到了PHP),在这种情况下,您必须拆分category_ids列值并组装自己的结果集
  3. 还有第三个解决方案,我发现它就像一个技巧(使用临时表和存储过程),首先你必须声明这个存储过程:

    DELIMITER $$
    CREATE PROCEDURE csv_Explode( sSepar VARCHAR(255), saVal TEXT )
    body:
    BEGIN
    
      DROP TEMPORARY TABLE IF EXISTS csv_Explode;
      CREATE TEMPORARY TABLE lib_Explode(
        `pos` int unsigned NOT NULL auto_increment,
        `val` VARCHAR(255) NOT NULL,
        PRIMARY KEY  (`pos`)
      ) ENGINE=Memory COMMENT='Explode() results.';
    
      IF sSepar IS NULL OR saVal IS NULL THEN LEAVE body; END IF;
    
      SET @saTail = saVal;
      SET @iSeparLen = LENGTH( sSepar );
    
      create_layers:
      WHILE @saTail != '' DO
    
        # Get the next value
        SET @sHead = SUBSTRING_INDEX(@saTail, sSepar, 1);
        SET @saTail = SUBSTRING( @saTail, LENGTH(@sHead) + 1 + @iSeparLen );
        INSERT INTO lib_Explode SET val = @sHead;
    
      END WHILE;
    
    END; $$
    DELIMITER ;
    

    然后你必须调用在你要爆炸的列中传递数组的过程:

    CALL csv_explode(',', (SELECT category_ids FROM products WHERE product_id = 100));
    

    在此之后,您可以通过以下方式在临时表中显示结果:

    SELECT * FROM csv_explode;
    

    结果集将是:

    +-----+-----+
    | pos | val |
    +-----+-----+
    |   1 | 200 |
    |   2 | 300 |
    +-----+-----+
    

    这可能是你的起点...