【问题标题】:Split value in columns by a delimiter and then Select Distinct按分隔符拆分列中的值,然后选择 Distinct
【发布时间】:2015-02-19 10:12:48
【问题描述】:

表结构

1_column 2_column
-----------------------------
1        data 1; data 2
2        data 3
3        data 1; data 15; data 6
4        data 2; data 3; data 16
5        data 3

查询SELECT DISTINCT 2_column FROM table ORDER BY 1_column

返回的输出是:4行。

data 1; data 2
data 3
data 1; data 15, data 6
data 2; data 3; data 16

现在我想分解列2_column 的值,例如数据1、数据2、数据3 等,然后在分解的值中分解SELECT DISTINCT。如何在考虑性能的同时仅使用 MySQL 来实现这一点?

编辑:预期结果:

data 1
data 2
data 3
data 6
data 15
data 16

爆炸的 DISTINCT 值。 6 行。

【问题讨论】:

  • 如果您考虑性能,每行只需一个数据...这将增加行数并允许您使用普通的 MySQL 函数进行投标。如果可以允许更改表结构,我会极力推荐它。另外,请添加您对 SELECT DISTINCT 的预期结果,因为它会使您的文字更有意义。
  • @Salketer:谢谢,已注意到您的建议并编辑了问题。

标签: php mysql


【解决方案1】:

显然,您需要规范化您的数据。但我想你可以使用这样的东西作为实现这一目标的一步......

SELECT * FROM my_table;
+---------+-------------------------+
| column1 | column2                 |
+---------+-------------------------+
|       1 | data 1; data 2          |
|       2 | data 3                  |
|       3 | data 1; data 15; data 6 |
|       4 | data 2; data 3; data 16 |
|       5 | data 3                  |
+---------+-------------------------+

SELECT * FROM ints;
+---+
| i |
+---+
| 0 |
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
+---+

SELECT DISTINCT TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(column2,';',i),';',-1)) x 
           FROM my_table
              , ints i 
         HAVING x <> '';
+---------+
| x       |
+---------+
| data 1  |
| data 3  |
| data 2  |
| data 15 |
| data 6  |
| data 16 |
+---------+

【讨论】:

    【解决方案2】:

    简单的方法如下:

    DELIMITER $$
    DROP PROCEDURE IF EXISTS getresults$$ 
    CREATE PROCEDURE getresults()
      BEGIN
        DECLARE ite INT;
        SET @s="";
        select MAX(LENGTH(2_column)-LENGTH(REPLACE(2_column, ";", "")))+1 max 
          FROM mytable INTO ite;
    
        WHILE (ite>0) DO
           SET @s=concat(@s, 
               "UNION SELECT ltrim(substring_index(
                   SUBSTRING_INDEX(2_column, ';', ",ite,"), ';', -1)) data
                FROM mytable ");
        SET ite:=ite-1;
        END WHILE;
        SET @s=mid(@s, 6);
        PREPARE stmt FROM @s;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
    
      END $$
    DELIMITER ;
    call getresults();
    
    +---------+
    | data    |
    +---------+
    | data 2  |
    | data 3  |
    | data 6  |
    | data 16 |
    | data 15 |
    | data 1  |
    +---------+
    

    【讨论】:

      【解决方案3】:

      我确实喜欢草莓答案,它比我以前的存储过程更简单

      如果你假设你不会有比行更多的“伪列”,你可以使用下面的指令来绕过创建 int 表的限制:

         SET @a:=0;
         SELECT DISTINCT TRIM(SUBSTRING_INDEX(
                  SUBSTRING_INDEX(2_column,';',a.nb),';',-1)) data
          FROM mytable,
             (SELECT @a:=@a+1 nb
                   FROM mytable
                   WHERE @a<
                    (SELECT MAX(LENGTH(m1.2_column)
                         -LENGTH(REPLACE(m1.2_column, ";", "")))+1 max
                       FROM mytable m1)) a;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-12
        • 2020-12-16
        相关资源
        最近更新 更多