我有一个自定义表单生成器,管理员可以在其中单独创建字段和表单,以便这些字段可以在多个表单上重复使用。管理员可以随时对字段重新排序,并添加新字段或删除现有字段,即使在提交后也是如此。我为此有 5 个表:
forms
、fields
、form_fields
链接表、submissions
和 submission_fields
表,它既是链接表,也包含提交字段的值。
如果字段的位置已移动,则问题在于现有提交的数据排序。在此 SQLFiddle 中,我模拟了表单的提交,其中字段的顺序为数字(1(名字)、2(姓氏)、3(电子邮件地址)、4(地址)、5(城市) 、6(州)、7(邮政编码)和 8(电话)),但随后电话号码字段 (#8) 在
email address
字段下向上移动,将顺序更改为 1、2、3、8, 4、5、6、7。
-- INIT database
CREATE TABLE forms (
id INT AUTO_INCREMENT KEY,
title VARCHAR(200)
);
CREATE TABLE fields (
id INT AUTO_INCREMENT KEY,
label VARCHAR(200)
);
CREATE TABLE form_fields (
id INT AUTO_INCREMENT KEY,
form_id INT,
field_id INT
);
CREATE TABLE submissions (
id INT AUTO_INCREMENT KEY,
form_id INT
);
CREATE TABLE submission_fields (
id INT AUTO_INCREMENT KEY,
submission_id INT,
field_id INT,
field_value VARCHAR(255)
);
INSERT INTO forms(title) VALUES ('Form 1');
INSERT INTO fields(label) VALUES ('First Name');
INSERT INTO fields(label) VALUES ('Last Name');
INSERT INTO fields(label) VALUES ('Email Address');
INSERT INTO fields(label) VALUES ('Address');
INSERT INTO fields(label) VALUES ('City');
INSERT INTO fields(label) VALUES ('State');
INSERT INTO fields(label) VALUES ('Zip');
INSERT INTO fields(label) VALUES ('Phone');
INSERT INTO form_fields(form_id, field_id) VALUES (1, 1);
INSERT INTO form_fields(form_id, field_id) VALUES (1, 2);
INSERT INTO form_fields(form_id, field_id) VALUES (1, 3);
INSERT INTO form_fields(form_id, field_id) VALUES (1, 8);
INSERT INTO form_fields(form_id, field_id) VALUES (1, 4);
INSERT INTO form_fields(form_id, field_id) VALUES (1, 5);
INSERT INTO form_fields(form_id, field_id) VALUES (1, 6);
INSERT INTO form_fields(form_id, field_id) VALUES (1, 7);
INSERT INTO submissions(form_id) VALUES (1);
INSERT INTO submission_fields(submission_id, field_id, field_value) VALUES (1, 1, 'Joe');
INSERT INTO submission_fields(submission_id, field_id, field_value) VALUES (1, 2, 'Smith');
INSERT INTO submission_fields(submission_id, field_id, field_value) VALUES (1, 3, '[email protected]');
INSERT INTO submission_fields(submission_id, field_id, field_value) VALUES (1, 4, '123 Main St');
INSERT INTO submission_fields(submission_id, field_id, field_value) VALUES (1, 5, 'Somewhere');
INSERT INTO submission_fields(submission_id, field_id, field_value) VALUES (1, 6, 'CA');
INSERT INTO submission_fields(submission_id, field_id, field_value) VALUES (1, 7, '90210');
INSERT INTO submission_fields(submission_id, field_id, field_value) VALUES (1, 8, '555-555-5555');
-- QUERY database
SELECT
submissions.id AS submission_id,
submissions.form_id AS form_id,
forms.title AS form_title,
GROUP_CONCAT(COALESCE(form_fields.field_id, '') SEPARATOR '|') AS field_ids,
GROUP_CONCAT(COALESCE(fields.label, '') SEPARATOR '|') AS field_labels,
(
SELECT
GROUP_CONCAT(COALESCE(submission_fields.field_value, '') SEPARATOR '|')
FROM
submission_fields
WHERE
submission_fields.submission_id = submissions.id
) AS field_values
FROM
submissions
LEFT OUTER JOIN
forms
ON
forms.id = submissions.form_id
LEFT OUTER JOIN
form_fields
ON
form_fields.form_id = submissions.form_id
LEFT OUTER JOIN
fields
ON
fields.id = form_fields.field_id
WHERE
submissions.id = 1
GROUP BY
submissions.id;
在主查询中,一切都正确返回。然而,在
field_ids
和 field_values
的子查询中,它们按原始顺序返回。因此,我需要将它们设置为与主查询中返回的顺序相同的顺序(field_values
应该将电话号码放在第 4 个位置,因为它是字段 ID 8,并出现在 field_ids
中的第 4 个位置)。
您可以在
ORDER BY form_fields.id ASC
内添加 GROUP_CONCAT
,以根据参考文献的顺序更改结果的顺序 (form_fields.id
)。
这是修改后的查询,其中包含您需要的结果:SQLFiddle
请注意,我还删除了子查询并加入
submission_fields
表,以简化脚本并轻松根据参考对结果进行排序。
这是完整的脚本:
-- QUERY database
SELECT
submissions.id AS submission_id,
submissions.form_id AS form_id,
forms.title AS form_title,
GROUP_CONCAT(COALESCE(form_fields.field_id, '') ORDER BY form_fields.id ASC SEPARATOR '|') AS form_fields_field_ids,
GROUP_CONCAT(COALESCE(fields.label, '') ORDER BY form_fields.id ASC SEPARATOR '|') AS field_labels,
GROUP_CONCAT(COALESCE(submission_fields.field_id, '') ORDER BY form_fields.id ASC SEPARATOR '|') AS field_ids,
GROUP_CONCAT(COALESCE(submission_fields.field_value, '') ORDER BY form_fields.id ASC SEPARATOR '|') AS field_values
FROM
submissions
LEFT OUTER JOIN
forms
ON
forms.id = submissions.form_id
LEFT OUTER JOIN
form_fields
ON
form_fields.form_id = submissions.form_id
LEFT OUTER JOIN
fields
ON
fields.id = form_fields.field_id
LEFT OUTER JOIN
submission_fields
ON
submission_fields.submission_id = submissions.id AND fields.id = submission_fields.field_id
WHERE
submissions.id = 1
GROUP BY
submissions.id;