将多行放到一行的最有效方法

时间:2012-01-20 19:37:43

标签: php mysql sql

我有一个表,其中插件保留所有表单提交,在此表中我为每个字段都有一行,如下所示:

1 'Name' 'Tony'
2 'Surname' 'Smith'
3 'Mail' 'tony@mail.com'
4 etc.

我想将所有这些数据都带到一个表中,其中所有数据都在列中,如下所示:

New_Id Name   Surname  Mail
     1 'Tony' 'Smith'  'tony@mail.com'
     2 'Mary' 'DotCom' 'mary@dotcom'

我有很多这些记录,所以效率很重要。我的第一种方法是在第一个表中的每个字段上进行PHP循环,然后决定是否必须在第二个表中插入或更新,此解决方案甚至可能需要先前选择以查看是否已填充字段,因此解决方案不是很好的。

您能想到更好的解决方案吗?

编辑:这是我的结构:

这是我的目标表,字段名称是西班牙语,但它们是name,birth_date,adress等。

create table target_table
    (id     int not null AUTO_INCREMENT,
    blog_id     int,
    submission_id   int,
    form_id     varchar(250) character set utf8 collate utf8_general_ci,
    submission_date timestamp,
    ip      varchar(250) character set utf8 collate utf8_general_ci,
    sitio           varchar(250) character set utf8 collate utf8_general_ci,
    nombre      varchar(4000) character set utf8 collate utf8_general_ci,
    fecha_nacimiento varchar(250),
    email           varchar(250) character set utf8 collate utf8_general_ci,
    direccion       varchar(250) character set utf8 collate utf8_general_ci,
    cp          varchar(250) character set utf8 collate utf8_general_ci,
    PRIMARY KEY(id));

源实际上是两个表,cforms_submissions是带有submission_id的父,submission_date和email:

id               int(11) unsigned PK
form_id          varchar(3)
sub_date         timestamp
email            varchar(40)
ip               varchar(15)

cforms_data是包含字段及其值的子表:

f_id             int(11) unsigned PK
sub_id           int(11) unsigned <---- This is FK to parent
field_name       varchar(100)
field_val        text

所以,我应该这样做:

select submissions....
for each submission
    select fields in submissions
    for each field in submission
        if first_field
            insert
        else
            update

也许有更好的方法?

谢谢,BTW,我正在使用MySql

1 个答案:

答案 0 :(得分:2)

抱歉,我误解了这个问题。 只要表的数量有限,你可以用以下方式进行N连接:

INSERT_INTO target_table(blog_id, form_id, ....) 
SELECT id, ..., name_table.field_val, address_table, ... 
FROM cforms_data name_table INNER JOIN cforms_data address_table 
    ON  name_table.sub_id = address_table.sub_id 
    INNER JOIN cforms_data date_table ON name_table.sub_id = name_table.sub_id
    INNER JOIN ...
WHERE name_table.field_name = 'NAME' AND address_table.field_name = 'ADDRESS' AND...

您正在做的是为目标中的每个字段获取与源中该字段匹配的条目子集,以及将其与具有相同ID的其他子集中的字段匹配的字段。 由于每个字段都有别名,因此查询将会非常痛苦,但如果正确编制索引(可能在field_name,sub_id上),性能不应该太差。我认为你可以在表单中添加field_name比较,但我不确定这是MySQL还是只有Oracle。 你可能需要电子邮件的父母,但我是微不足道的

<强> ORIGINAL:

只需在MySql中执行

  

INSERT INTO target_table(blog_id,form_id ....)SELECT id,form_id ,,   ....,... FROM Cforms_submissions INNER JOIN cforms_data ON id ==   sub_id HAVING MAX(sub_date)

我假设您要插入最后一条记录。否则,相应地改变SELECT。 INSERT INTO中的字段必须与SELECT中的字段匹配。