多行文本字段用于分隔MySQL中的字段

时间:2013-02-10 21:44:52

标签: mysql

所以我有一个地址TEXT字段,我需要将其拆分成单独的字段,例如: “physical_address”字段包含以下内容:

| physical_address |
+------------------+
| 123 Street Name  |
| Suburb           |
| City             |
+------------------+

会变成:

| physical_address_1 | physical_address_2 | physical_address_3 |
+--------------------+--------------------+--------------------+
| 123 Street Name    | Suburb             | City               |
+--------------------+--------------------+--------------------+

现在这只是暂时的,因为我需要以上述格式将其导入应用程序,因此select语句将是最佳选择 - 尽管我认为它不会那么简单。

这种作品,但并不完全:

SELECT
physical_address,
SUBSTRING_INDEX(physical_address, CHAR(10), -5) AS a,
SUBSTRING_INDEX(physical_address, CHAR(10), -4) AS b,
SUBSTRING_INDEX(physical_address, CHAR(10), -3) AS c,
SUBSTRING_INDEX(physical_address, CHAR(10), -2) AS d,
SUBSTRING_INDEX(physical_address, CHAR(10), -1) AS e
FROM clients LIMIT 5

使用5行TEXT值,效果很好,任何更少,你会看到前几个字段(取决于行)将重复值。 无法为此cos设置SQL小提琴它似乎正在清理我的返回提要,所以这是示例模式:

CREATE TABLE clients (id int unsigned auto_increment primary key, physical_address text);

INSERT INTO clients (id,physical_address) VALUES (1,"123 Street,\r\n123 Suburb,\r\n123 City");
INSERT INTO clients (id,physical_address) VALUES (2,"456 Street,\r\n456 Suburb,\r\n456 City,\r\n456 Province");
INSERT INTO clients (id,physical_address) VALUES (3,"789 Street,\r\n789 Suburb,\r\n789 City,\r\n789 Province,\r\n789 Country");

2 个答案:

答案 0 :(得分:1)

假设您有某种方法可以识别特定用户的每个地址,等等。如果是这样,那么您可以使用用户定义的变量来分配行号,然后 pivot 使用具有CASE表达式的聚合函数:

select id,
  max(case when rn=1 then physical_address end) Physical_address1,
  max(case when rn=2 then physical_address end) Physical_address2,
  max(case when rn=3 then physical_address end) Physical_address3
from
(
  select t.physical_address,
    id,
    @row:=case when @prev=id then @row else 0 end +1 rn,
    @prev:=id
  from yourtable t
  cross join (select @row:=0, @prev:=0)r
  order by t.id
) src
group by id
order by id

请参阅SQL Fiddle with Demo

如果地址数据在一行中,那么您需要先将数据拆分成多行,然后将其旋转为列。

我创建了一个用于拆分数据的函数和过程。我的代码基于@Johan's answer here

首先,我创建了clients表的备用版本:

CREATE TABLE clients_new
    (id int,`physical_address` varchar(256))
;

然后我创建了函数/过程:

CREATE FUNCTION strSplit(x VARCHAR(5000), delim VARCHAR(12), pos INTEGER) 
RETURNS VARCHAR(256)
BEGIN
  DECLARE output VARCHAR(256);
  SET output = REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos)
                 , LENGTH(SUBSTRING_INDEX(x, delim, pos - 1)) + 1)
                 , delim
                 , '');
  IF output = '' THEN SET output = null; END IF;
  RETURN output;
END //


CREATE PROCEDURE BadTableToGoodTable()
BEGIN
  DECLARE i INTEGER;

  SET i = 1;
  REPEAT
    INSERT INTO Clients_new (id, physical_address)
      SELECT id, strSplit(physical_address, '\r\n', i) 
      FROM Clients
      WHERE strSplit(physical_address, '\r\n', i) IS NOT NULL;
    SET i = i + 1;
    UNTIL ROW_COUNT() = 0
  END REPEAT;
END //

要执行该程序,您将使用:

call BadTableToGoodTable;

一旦完成拆分数据的过程,您就可以使用我提供的原始查询以及一些小编辑来包含新表和其他列(如果需要):

select id,
  max(case when rn=1 then physical_address end) Physical_address1,
  max(case when rn=2 then physical_address end) Physical_address2,
  max(case when rn=3 then physical_address end) Physical_address3,
  max(case when rn=4 then physical_address end) Physical_address4,
  max(case when rn=5 then physical_address end) Physical_address5
from
(
  select t.physical_address,
    id,
    @row:=case when @prev=id then @row else 0 end +1 rn,
    @prev:=id
  from clients_new t
  cross join (select @row:=0, @prev:=0)r
  order by t.id
) src
group by id
order by id

答案 1 :(得分:0)

您可以选择所有内容,然后在php中使用explode(“/ n”)对其进行切片。接下来将其保存到数据库中。它不可能从mySQL级别开始