MySQL - convert names and values into columns - mysql

I have the following 2 tables:
Parameters table: ID, EntityType, ParamName, ParamType
Entity table: ID, Type, Name, ParamID, StringValue, NumberValue, DateValue
Entity.ParamID is linked to Parameters.ID
Entity.Type is linked to Parameters.EntityType
StringValue, NumberValue, DateValue contains data based on Parameters.Type (1,2,3)
the query result should contain:
Entity.ID, Entity.Name, Parameters.ParamName1, Parameters.ParamName2... Parameters.ParamNameX
The content of ParamNameX is as the above correlation. How is it possible to turn the parameters names into columns and their values into data of those columns? I don't even know where to begin.
Explanation for the above: for example entity X can be entitytype 1 and entitytype 2. parameters table contains paramname for both type 1 and 2 but I need to get (for example) only entity type 1's paramname.

What you are trying to archive is a EAV (Entity Attribute Value) Model.
But the way you set up your tables is just wrong.
You should have a table per type.
So entity_string, entity_number, entity_date and a main table entity which holds the id and some general stuff like create_time, update_time and so on.
Look at magento and how they set up their tables. Like this it is much easier to ask for your data and organize it.

Related

MySQL SELECT Key Value table as row

I have the following MySQL table "application_session" with the following columns:
- applicationId
- applicationKey
- applicationVal
- applicationDate
This table has many key/value pairs in it, keys and vals can change, new pairs can be added or removed. Furthermore, every "applicationId" can have different key/value pairs from others.
What's the best way to dynamically return (SELECT query) all pairs in a rows where "applicationKey" is the column name and "applicationVal" the result?
I hope I'm explaining things right.

normalization of database structure

I was reading the concept of normalization of database structure. I got confused with the following situation in my project.
I have two tables "TableA" and TableB
Both tables are independent of each other and have no realtionship at all
They represent completely different data
Both the tables will have different parameters. However Parameter itself as an object has same properties.
So my concern is should I have single Parameter table which is serving TableA and TableB both
Or
I should have separate Parameter Table for both Table A and Table B
Structure look likes this
Case I:
TableA
ID
Name
Description
TableB
ID
Name
SomeFlag
Parameter
ID
TableA_ID
TableB_ID
Name
Description
Type
Case II
TableA
ID
Name
Description
Parameter_A
ID
TableA_ID
Name
Description
Type
TableB
ID
Name
SomeFlag
Parameter_B
ID
TableB_ID
Name
Description
Type
I personally prefer Case I, as it does make sense to create another table representing same type of data.
As per normalization's concept we should have a table that represents only one thing. So i guess i should have only one parameter table. But what if that table mean something completely different when viewed from TableA and different when viewed from TableB?
I would use case one but with some changes. The parameter entity does hold one thing, parameters for a table. An instance of a parameter entry should relate to only one table (based on your analysis that they are not related).
Parameter
----------
PK Param_ID
FK Main_Table_ID
Main_Table_name (A or B)
param_Name
param_Description
param_Type
If it makes logical sense for a Parameter to have both Table A and Table B in the same instance (not an either/or), then Case I is better.
In Relational Theory, every table is a type. Even if they may have common data, types are based around their usage. And though it's a little more complicated, Case II is more normalized.
There is another possibiltiy, that hasn't been mentioned, I'll call it Case III.
TableA
ID
Name
Description
PropertyID
TableB
ID
Name
SomeFlag
PropertyID
Parameter
ID
Name
Description
Type
If the Properties will always be common among both tables, this is probably going to be the best solution.

Select all full records in a supertype/subtype SQL pattern

In a relational supertype/subtype structure where, for example, I have a supertype table entity with an entity_type column and a number of subtype tables, is there any way I can go about querying all entities with their full records, that is somehow joining to each of the subtype tables automatically?
So, with:
TABLE entity
-- entity_id (INT pk)
-- entity_type_id (INT fk)
TABLE entity_type
-- entity_type_id (INT pk)
-- name //Person, Building, Animal (TEXT)
TABLE person
-- entity_id (INT fk)
-- person_name (TEXT)
-- person_age (INT)
TABLE building
-- entity_id (INT fk)
-- age_built (INT)
etc.
what if I wanted to query all entities, and in my result set get all person-specific columns (person_name, etc.) if the record was a person and age_built, etc. if the record was a building? I thought about storing the subtype table names in the type table but understand you can't dynamically reference those like that.
Am I being an ignorant DB newb here or is this in any way possible without explicitly defining the join and doing a query for each subtype table?
I'm asking this because elsewhere in my DB I'm going to have a lot of references to an entity_id (that could be any kind of entity) and I don't want to run an initial query to just to check its type first.
Working in MySQL, no preference to engine.
Don't do this unless you really know what you are doing (and then probably don't do it!). This fits into the entity attribute value anitpattern. Better to model out the entities which relate to each person/animal/building separately.
https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:2314483800346542969
Either that or you could consider having multiple fk columns from entity type to the linked entities. How many entities are you expecting to reference entity_type?

Providing initial data for a many-to-many table in Django

I want to clarify the format of providing initial data in raw SQL for a Django model that uses a many to many relationship. I've based my query on this example. I know I'm not required to specify the through parameter in ManyToManyField for this case, but I would like to have the table listed explicitly.
Backend db is MySQL & table names are lowercase Class names.
Model :
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
I suppose the correct way to provide data would be :
INSERT INTO person VALUES ('Ringo Starr')
INSERT INTO person VALUES ('Paul McCartney')
INSERT INTO group VALUES ('The Beatles')
INSERT INTO membership VALUES (1, 1)
INSERT INTO membership VALUES (2, 1)
How will I specify this data if I did not declare the Membership table explicitly and didn't use the through parameter? Is the following correct?
INSERT INTO person VALUES ('Ringo Starr')
INSERT INTO person VALUES ('Paul McCartney')
INSERT INTO group VALUES ('The Beatles', 1)
INSERT INTO group VALUES ('The Beatles', 1)
UPDATE : The second method isn't correct. The members field under Group class isn't a real dB column.
Short answer:
The correct way to do it in SQL is the same as when you use through, but the table that was membership before will either have a name generated by Django like person_group_a425b, or a name you specify with the db_table parameter on Group.members.
More details:
Even if you don't make a model explicitly for the table that joins them together, Django will create a join table for them.
From the Django docs about how the table is named:
Behind the scenes, Django creates an intermediary join table to represent the
many-to-many relationship. By default, this table name is generated using the name of
the many-to-many field and the name of the table for the model that contains it. Since
some databases don’t support table names above a certain length, these table names will
be automatically truncated to 64 characters and a uniqueness hash will be used. This
means you might see table names like author_books_9cdf4; this is perfectly normal.
You can provide a shorter/different name for the join table in the definition of the ManyToManyfield, using the db_table option.

Handling custom user fields with possibility of grow and shrink

This question is much about how to do, idea etc.
I have a situation where a user can create as many custom fields as he can of type Number, Text, or Date, and use this to make a form. I have to make/design some table model which can handle and store the value so that query can be done on these values once saved.
Previously I have hard coded the format for 25 user defined fields (UDF). I make a table with 25 column with 10 Number, 10 Text, and 5 Date type and store the label in it if a user makes use of any field. Then map it to other table which has same format and store the value. Mapping is done to know which field is having what label but this is not an efficient way, I hope.
Any suggestion would be appreciated.
Users have permissions for creating any number of UDF of the above types. then it can be used to make forms again this is also N numbers and have to save the data for each form types.
e.g. let's say a user created 10 number 10 date and 10 text fields used first 5 of each to make form1 and all 10 to make form2 now saved the data.
My thoughts on it:
Make a table1 with [id,name(as UDF_xxx where xxx is data type),UserLabel ]
table2 to map form and table1 [id(f_key table1_id), F_id(form id)]
and make 1 table of each data type as [ id(f_key of table1),F_id(form number),R_id(row id for data, would be same for all data type),value]
Thanks to all I'm going to implement, it both DataSet entry and json approach looks good as it gives wider extension-ability. Still I've to figure out which will best fit with the existing format.
There are two approaches I have used.
XML: To create a dynamic user attribute, you may use XML. This XML will be stores in a clob column - say, user_attributes. Store the entire user-data in XML key-value pair, with type as an attribute or another field. This will give you maximum freedom. You can use XOM or any other XML object Model API to display or operate on the data. A typical Node will look like
<userdata>
...
...
<datanode>
<key type="Date">User Birth</key>
<value>1994-02-25</value>
</datanode>
...
</userdata>
Attribute-AttributeValue This is same thing as above but using tables. What you do is you create a table -- attributes with FK as user_id, another table attribute_values with FK as attribute_id. attributes contains multiple field-names and types for each user and attribute_values contains values of those attributes. so basically,
users
user_id
attributes
attr_id
user_id (FK)
attr_type
attr_name
attribute_values
attr_val_id
attr_id (FK)
attr_val
If you see in both the approached you are not limited by how-many or what type of data you have. But there is a down-side of this is parsing. In either of the case, you will have to to do a small amount of processing to display or analyze the data.
The best of both worlds (having rigid column structure vs having completely dynamic data) approach is to have a users table with must-have columns (like user_name, age, sex, address etc) and have user-created data (like favorite pet house etc.) in either XML or attribute-attribute_value.
What do you want to achieve?
A table per form permutation or might each dataset consist of different sets?
Two possibilities pop into my mind:
Create a table that describes one field of a dataset, i.e. the key might be dataset id + field id and additional columns could contain the value stored as a string and the type of that value (i.e. number, string, boolean, etc.).
That way each dataset might be different but upon reading a dataset and storing it into an object you could create the appropriate value types (Integer, Double, String, Boolean etc.)
Create a table per form, using some naimg convention. When the form layout is changed, execute ALTER TABLE statements to add, remove, rename columns or change their type.
When the user changes the type of a column or deletes it, you might need to either deny that if the values are not null or at least ask the user if she's willing to drop values that don't match the new requirements.
Edit: Example for approach 1
Table UDF //describes the available fields--------
id (PK)
user_id (FK)
type
name
Table FORM //describes a form's general attributes--------
id (PK)
user_id (FK)
name
description
Table FORM_LAYOUT //describes a form's field layout--------
form_id (FK)
udf_id (FK)
mapping //mapping info like column index, form field name etc.
Table DATASET_ENTRY //describes one entry of a dataset, i.e. the value of one UDF in
--------
id (PK)
row_id
form_id (FK)
udf_id (FK)
value
Selecting the content for a specific form might then be done like this:
SELECT e.value, f.type, l.mapping from DATASET_ENTRY e
JOIN UDF f ON e.udf_id = f.id
JOIN FORM_LAYOUT l ON e.form_id = l.form_id AND e.udf_id = l.udf_id
WHERE e.row_id = ? AND e.form_id = ?
Create a table which manages which fields exist. Then create tables for each data type you want to support, where the user will their values into.
create table Fields(
fieldid int not null,
fieldname text not null,
fieldtype int not null
);
create table FieldDate
(
ValueId int not null,
fieldid int not null,
value date
);
create table FieldNumber
(
ValueId int not null,
fieldid int not null,
value number
);
..
Another possibility would be to use ALTER TABLE to create custom fields. If your application has the rights to perform this command and the custom fields are changing very rarely this would be the option I chose.