2012-06-19 89 views
2

MySQL。两列,同一张桌子。
第1列的product_id
第2列具有category_ids(有时2个类别,所以看起来像23,43)

如何编写一个查询返回的PRODUCT_ID,category_ids列表,与一个单独的行,如果有与product_id关联的是多于1个category_id。
将结果中逗号分隔的值从一列分隔为两行。 MySQL


表:

product_id | category_ids 
100  | 200,300 
101  | 201 

查询结果:不试图修改表

100 | 200 
100 | 300 
101 | 201 


编辑:(注)我真的不希望来操纵桌子。只是在PHP中进行查询,所以我可以根据需要使用这些数据。

+0

你为什么要节约category_ids逗号分隔?这不是标准化的形式。你想要的结果结构应该在那里。 –

+0

这几乎是这个问题的确切副本:http://stackoverflow.com/questions/10293861/split-comma-seperated-values-in-column-mysql/10294021#10294021 –

+0

另一个问题是一个确切的副本:http ://stackoverflow.com/questions/4890968/comma-seperated-value-seperation –

回答

1

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

有两种可行的解决方案:

  1. 更改您存储数据的方式(允许在product_id领域的重复,并把多条记录与同product_id针对不同category_id
  2. 操纵从查询结果在您的应用程序中(您在您的问题中提到了PHP),在这种情况下,您必须拆分category_ids列值并组装自己的结果集

还有,我已经找到了第三个方案就是喜欢一招(使用临时表和存储过程),首先你的声明此存储过程:

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

这可能是你的起点......

+0

一个开发者在这之前为我实现了类似的东西(但我不知道如何翻译和使用再次):SELECT p.prodname,c.combinationid,CONCAT(o.voname),CONCAT(vovalue) FROM isc_product_variation_combinations为C LEFT JOIN isc_product_variation_options邻 ON FIND_IN_SET(o.voptionid,c.vcoptionids) LEFT JOIN isc_products AS p ON p.productid = c.vcproductid WHERE c.vcproductid = 255 – jason3w

+0

尽管这是结合了几张表中的数据。所以认为只用一张桌子可能会很容易。 – jason3w

+0

您发布的查询连接两个不同的表格,是另一回事。在这种情况下,你有一个单一的ID表,你使用FIND_IN_SET函数加入该列... – aleroot