[nycphp-talk] Flexible Forms & How to store them...
Mark Armendariz
lists at enobrev.com
Tue May 15 13:31:13 EDT 2007
> -----Original Message-----
> [mailto:talk-bounces at lists.nyphp.org] On Behalf Of Brian Dailey
> Sent: Tuesday, May 15, 2007 10:45 AM
> Another way I've seen it handled is to have a
> header table and a detail table that works something like this:
>
> table: documents (id, date, etc)
> table: documentdetails (documentid, fieldname, fieldvalue)
>
> All of the form values were stored in a fieldname=fieldvalue
> format inside the table. This worked nicely until you
> attempted to run reports on it - you couldn't easily combine
> data since it all existed in different table rows.
Reports aren't too difficult. It depends on how in-depth your reports get.
Essentially you end up joining the data table for every field. I haven't
done this in quite some time, but here's the idea of how you run reports
when using field-value tables (tested in mysql 4.0.23)
CREATE TABLE data (
data_id TINYINT(3) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
data_user VARCHAR(100)
)
CREATE TABLE data_fields (
field_id MEDIUMINT(6) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
data_id TINYINT(3) UNSIGNED NOT NULL,
field_name VARCHAR(20),
field_data VARCHAR(100)
)
INSERT INTO data (data_user) VALUES ('mark at example.com');
INSERT INTO data (data_user) VALUES ('brian at example.com');
INSERT INTO data (data_user) VALUES ('steve at example.com');
INSERT INTO data_fields (data_id, field_name, field_data) VALUES (1, 'name',
'Mark');
INSERT INTO data_fields (data_id, field_name, field_data) VALUES (1, 'city',
'Brooklyn');
INSERT INTO data_fields (data_id, field_name, field_data) VALUES (1,
'state', 'NY');
INSERT INTO data_fields (data_id, field_name, field_data) VALUES (2, 'name',
'Brian');
INSERT INTO data_fields (data_id, field_name, field_data) VALUES (2, 'city',
'New York');
INSERT INTO data_fields (data_id, field_name, field_data) VALUES (2,
'state', 'NY');
INSERT INTO data_fields (data_id, field_name, field_data) VALUES (3, 'name',
'Steve');
INSERT INTO data_fields (data_id, field_name, field_data) VALUES (3, 'city',
'Jersey City');
INSERT INTO data_fields (data_id, field_name, field_data) VALUES (3,
'state', 'NJ');
// All data with Name, City and State
SELECT d.data_id,
d.data_user,
fName.field_data AS Name,
fCity.field_data AS City,
fState.field_data AS State
FROM data d LEFT JOIN data_fields fName ON d.data_id = fName.data_id AND
fName.field_name = 'name'
LEFT JOIN data_fields fCity ON d.data_id = fCity.data_id AND
fCity.field_name = 'city'
LEFT JOIN data_fields fState ON d.data_id = fState.data_id AND
fState.field_name = 'state';
// output
+---------+-------------------+-------+-------------+-------+
| data_id | data_user | Name | City | State |
+---------+-------------------+-------+-------------+-------+
| 1 | mark at example.com | Mark | Brooklyn | NY |
| 2 | brian at example.com | Brian | New York | NY |
| 3 | steve at example.com | Steve | Jersey City | NJ |
+---------+-------------------+-------+-------------+-------+
// data with Name, City, State in NY
SELECT d.data_id,
d.data_user,
fName.field_data AS Name,
fCity.field_data AS City,
fState.field_data AS State
FROM data d LEFT JOIN data_fields fName ON d.data_id = fName.data_id AND
fName.field_name = 'name'
LEFT JOIN data_fields fCity ON d.data_id = fCity.data_id AND
fCity.field_name = 'city'
LEFT JOIN data_fields fState ON d.data_id = fState.data_id AND
fState.field_name = 'state';
HAVING(State = 'NY');
// output
+---------+-------------------+-------+----------+-------+
| data_id | data_user | Name | City | State |
+---------+-------------------+-------+----------+-------+
| 1 | mark at example.com | Mark | Brooklyn | NY |
| 2 | brian at example.com | Brian | New York | NY |
+---------+-------------------+-------+----------+-------+
// data with Name, City, State in Brooklyn
SELECT d.data_id,
d.data_user,
fName.field_data AS Name,
fCity.field_data AS City,
fState.field_data AS State
FROM data d LEFT JOIN data_fields fName ON d.data_id = fName.data_id AND
fName.field_name = 'name'
LEFT JOIN data_fields fCity ON d.data_id = fCity.data_id AND
fCity.field_name = 'city'
LEFT JOIN data_fields fState ON d.data_id = fState.data_id AND
fState.field_name = 'state';
HAVING(City = 'Brooklyn');
// output
+---------+------------------+------+----------+-------+
| data_id | data_user | Name | City | State |
+---------+------------------+------+----------+-------+
| 1 | mark at example.com | Mark | Brooklyn | NY |
+---------+------------------+------+----------+-------+
// using WHERE instead of HAVING
SELECT d.data_id,
d.data_user,
fName.field_data AS Name,
fCity.field_data AS City,
fState.field_data AS State
FROM data d LEFT JOIN data_fields fName ON d.data_id = fName.data_id AND
fName.field_name = 'name'
LEFT JOIN data_fields fCity ON d.data_id = fCity.data_id AND
fCity.field_name = 'city'
LEFT JOIN data_fields fState ON d.data_id = fState.data_id AND
fState.field_name = 'state';
WHERE fCity.field_data = 'Brooklyn'
AND fState.field_data = 'NY';
// output
+---------+------------------+------+----------+-------+
| data_id | data_user | Name | City | State |
+---------+------------------+------+----------+-------+
| 1 | mark at example.com | Mark | Brooklyn | NY |
+---------+------------------+------+----------+-------+
// EXPLAIN output of the last statement ('having' is a bit less efficient)
+--------+--------+---------------+------------+---------+---------------+--
----+-------------+
| table | type | possible_keys | key | key_len | ref |
rows | Extra |
+--------+--------+---------------+------------+---------+---------------+--
----+-------------+
| fCity | ref | field_name | field_name | 120 | const,const |
1 | Using where |
| d | eq_ref | PRIMARY | PRIMARY | 1 | fCity.data_id |
1 | |
| fName | ref | field_name | field_name | 20 | const |
2 | Using where |
| fState | ref | field_name | field_name | 120 | const,const |
2 | Using where |
+--------+--------+---------------+------------+---------+---------------+--
----+-------------+
Hope that helps.
Good luck!!
Mark Armendariz
More information about the talk
mailing list