Microsoft Access creating key-value column with formatting (lookup) - ms-access

I've been looking around but cannot seem to find a simple solution to this. I've got a simple Access database with a few tables, and I'd like to create a new column that contains a value in this format <REFERENCE ID> - <LETTER>. The reference ID can be directly extracted from a column (column A in example), but the letter needs to change based on the value of a different column. Is there any way to do this without nested IF conditions? Something like a key-value mapping table where I can specify that the LETTER (in the above format) should be be looked up like this:
Lookup table:
| Key |Val|
|---------|---|
| Key 1 | A |
| Key 2 | B |
| Key 3 | C |
| Key 4 | D |
Original reference ID table with associated keys:
| Reference ID | Keys |
|--------------|-------|
| 1000 | Key 1 |
| 1001 | Key 3 |
| 1002 | Key 4 |
| 1003 | Key 1 |
| 1004 | Key 2 |
New column (the one I'd like to create based off of the answer to the question):
| New column |
|--------------|
| 1000 - A |
| 1001 - C |
| 1002 - D |
| 1003 - A |
| 1004 - B |
As you can see, in this case, values are string literals. Keys are picked from a column with data validated fields.

Create a query that pulls in the values.
So,
SELECT [Reference ID], [Keys], [Val] FROM FirstTable
LEFT JOIN SecondTable ON SecondTable.Key = FirstTable.Keys
So, now use the query in place of the table. It will show all the columns, and pull in and translate the key value out to what you want.

Related

MySql add relationships without creating dupes

I created a table (t_subject) like this
| id | description | enabled |
|----|-------------|---------|
| 1 | a | 1 |
| 2 | b | 1 |
| 3 | c | 1 |
And another table (t_place) like this
| id | description | enabled |
|----|-------------|---------|
| 1 | d | 1 |
| 2 | e | 1 |
| 3 | f | 1 |
Right now data from t_subject is used for each of t_place records, to show HTML dropdowns, with all the results from t_subject.
So I simply do
SELECT * FROM t_subject WHERE enabled = 1
Now just for one of t_place records, one record from t_subject should be hidden.
I don't want to simply delete it with javascript, since I want to be able to customize all of the dropdowns if anything changes.
So the first thing I though was to add a place_id column to t_subject.
But this means I have to duplicate all of t_subject records, I would have 3 of each, except one that would have 2.
Is there any way to avoid this??
I thought adding an id_exclusion column to t_subject so I could duplicate records only whenever a record is excluded from another id from t_place.
How bad would that be?? This way I would have no duplicates, so far.
Hope all of this makes sense.
While you only need to exclude one course, I would still recommend setting up a full 'place-course' association. You essentially have a many-to-many relationship, despite not explicitly linking your tables.
I would recommend an additional 'bridging' or 'associative entity' table to represent which courses are offered at which places. This new table would have two columns - one foreign key for the ID of t_subject, and one for the ID of t_place.
For example (t_place_course):
| place_id | course_id |
|----------|-----------|
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
| 3 | 1 |
| 3 | 3 |
As you can see in my example above, place 3 doesn't offer course 2.
From here, you can simply query all of the courses available for a place by querying the place_id:
SELECT * from t_place_course WHERE place_id = 3
The above will return both courses 1 and 3.
You can optionally use a JOIN to get the other information about the course or place, such as the description:
SELECT `t_course`.`description`
FROM `t_course`
INNER JOIN `t_place_course`
ON `t_course`.`id` = `t_place_course`.`course_id`
INNER JOIN `t_place`
ON `t_place`.`id` = `place_id`

Filtering on text column: full-text or separate table

I have a table like so, which has 1 million+ rows:
+----+----------+----------------+------------+
| ID | SSID | MAC | LOCATION |
+----+----------+----------------+------------+
| 1 | home_net | aa:bb:cc:dd:ee | Town North |
| 2 | fly-fi | aa:bb:cc:dd:ff | Town South |
+----+----------+----------------+------------+
I often need to search for all rows with a given location. I have three ideas to structure the data so that I can filter based on location without using the slow "LIKE":
Add a fulltext index to the location column.
Create a new table for location and have a foreign key in the above table. Then I could filter based on the foreign key.
Create the table from point 2, and create a join table, like so:
+-------------+-----------+
| LOCATION ID | PROBE_IDS |
+-------------+-----------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 1 | 4 |
| 2 | 5 |
| 2 | 6 |
| 2 | 7 |
+-------------+-----------+
Which of these options, or another, is best to structure the data given that many queries will be carried out which filter by location.
Since this is a many-to-1 relationship, I would use option #2, the foreign key. The join table is more appopriate for many-to-many relationships.
The full-text index seems too heavyweight for short phrases like this. It might not even work for many locations, because full-text indexing has a minimum word length that it will index.

Store string and foreign key in one column

I'm building a website with a large number of categories, each with its own specific form fields. Because there are so many categories, I wanted to store those form fields in a database.
The categories are stored in a category table:
id | name
-------------
1 | Car info
The fields for that category are stored in a category_field table:
id | fk_id_category | type | label
-------------------------------------------------------------
1 | 1 | text | Your name
2 | 1 | radio | What type of car do your drive?
If a category_field has some predefined options from which the user can choose then these are stored in a category_field_option table:
id | fk_id_category_field | label
-----------------------------------------
1 | 2 | 'Convertible'
2 | 2 | 'Truck'
3 | 2 | 'Minivan'
Now, when a user fills out a form we want to save a reference to this in a form_entry table:
id | fk_id_user | fk_id_category
--------------------------------
1 | 1 | 1
The details of that form entry are saved in a form_entry_details table. However:
If the category_field.type is text we should just save the answer as string
id | fk_id_form_entry | fk_id_category_field | [answer]
-------------------------------------------------------
1 | 1 | 1 | John Doe
If the category_field.type is radio, I want to save a foreign key to the category_field_option
id | fk_id_form_entry | fk_id_category_field | [fk_id_category_field_option]
--------------------------------------------------------------------------
2 | 1 | 2 | 2
How can I solve this? I know I could just store the fk_id_category_field_option as a string, but I need it to actually reference to the category_field_option table since I'm using an ORM (Doctrine 1.2.4).
You can't because the whole idea of foreign keys is to prevent this sort of situation. You either store it as one field without an enforce foreign key or you create two columns, one for the foreign key id (perhaps a default value that relates to 'user defined') and another that takes the user defined info and, probably, defaults to null.

mysql: how to split list field

I have a table which only contains id and a field whose data is a list of data. e.g.
--------------
| id | data |
| 1 | a,b,c,d|
| 2 | a,b,k,m|
---------------
I guess it's not a good design that put a list data in a field, so I want to know how can I redesign it?
As per me you need two tables i.e. Master and Transaction tables only when some details are gonna be same for every records and some are gonna be changing. In your case if there are not any other thing related to your id field is gonna be same you can carry on with one table and with following structure.
--------------
| id | data |
| 1 | a |
| 1 | b |
| 1 | c |
| 1 | d |
| 2 | a |
| 2 | b |
| 2 | k |
| 2 | m |
---------------
BUT if there are any other things related to the id fields that is gonna be same for same id records you will have to use two tables.
like following case. there are 3 fields id, name and data.
and you current table looks something like
--------------------------
| id | name | data |
| 1 | testname | a,b,c,d|
| 2 | remy | a,b,c,d|
--------------------------
your new table structure should look like.
table 1 Master
-----------------
| id | name |
| 1 | testname |
| 2 | remy |
-----------------
Table 2 Transaction
--------------
| id | data |
| 1 | a |
| 1 | b |
| 1 | c |
| 1 | d |
| 2 | a |
| 2 | b |
| 2 | k |
| 2 | m |
---------------
For better database management we might need to normalize the data.
Database normalization is the process of organizing the fields and tables of a relational database to minimize redundancy and dependency. Normalization usually involves dividing large tables into smaller (and less redundant) tables and defining relationships between them. The objective is to isolate data so that additions, deletions, and modifications of a field can be made in just one table and then propagated through the rest of the database via the defined relationships. You can find more on below links
3 Normal Forms Database Tutorial
Database normalization
If you have only those two fields in your table then you should have only 1 table as below
id | data
with composite primary key as PRIMARY KEY(id,data) so that there won't be any duplicate data for the respective ID.
The data would be like this
id | data
1 | a
1 | b
1 | c
1 | d
2 | a
2 | b
2 | k
2 | m
You will need another table which can be of the ONE to MANY type.
For e.g. you could have another table datamapping which would have data and ID column where the ID column is a FOREIGN KEY to the ID column of the data table.
So according to your example there would be 4 entries for ID = 1 in the datamapping table.
You will need two tables with a foreign key.
Table 1
id
Table 2
id
datavalue
So the data looks like:
Table 1:
id
1
2
3
Table 2:
id | data
1 | a
1 | b
1 | c
1 | d
2 | a
2 | b
2 | k
2 | m
You are correct, this this is not a good database design. The data field violates the principle of atomicity and therefore the 1NF, which can lead to problems in maintaining and querying the data.
To normalize your design, split the original table in two. There are 2 basic strategies to do it: using non-identifying and using identifying relationship.
NOTE: If you only have id in the parent table, and no other FKs on it, and parent cannot exist without at least one child (i.e. data could not have been empty in the original design), you can dispense with the parent table altogether.

How to split CSVs from one column to rows in a new table in MSSQL 2008 R2

Imagine the following (very bad) table design in MSSQL2008R2:
Table "Posts":
| Id (PK, int) | DatasourceId (PK, int) | QuotedPostIds (nvarchar(255)) | [...]
| 1 | 1 | | [...]
| 2 | 1 | 1 | [...]
| 2 | 2 | 1 | [...]
[...]
| 102322 | 2 | 123;45345;4356;76757 | [...]
So, the column QuotedPostIds contains a semicolon-separated list of self-referencing PostIds (Kids, don't do that at home!). Since this design is ugly as a hell, I'd like to extract the values from the QuotedPostIds table to a new n:m relationship table like this:
Desired new table "QuotedPosts":
| QuotingPostId (int) | QuotedPostId (int) | DatasourceId (int) |
| 2 | 1 | 1 |
| 2 | 1 | 2 |
[...]
| 102322 | 123 | 2 |
| 102322 | 45345 | 2 |
| 102322 | 4356 | 2 |
| 102322 | 76757 | 2 |
The primary key for this table could either be a combination of QuotingPostId, QuotedPostId and DatasourceID or an additional artificial key generated by the database.
It is worth noticing that the current Posts table contains about 6,300,000 rows but only about 285,000 of those have a value set in the QuotedPostIds column. Therefore, it might be a good idea to pre-filter those rows. In any case, I'd like to perform the normalization using internal MSSQL functionality only, if possible.
I already read other posts regarding this topic which mostly dealt with split functions but neither could I find out how exactly to create the new table and also copying the appropriate value from the Datasource column, nor how to filter the rows to touch accordingly.
Thank you!
€dit: I thought it through and finally solved the problem using an external C# program instead of internal MSSQL functionality. Since it seems that it could have been done using Mikael Eriksson's suggestion, I will mark his post as an answer.
From comments you say you have a string split function that you you don't know how to use with a table.
The answer is to use cross apply something like this.
select P.Id,
S.Value
from Posts as P
cross apply dbo.Split(';', P.QuotedPostIds) as S