Lookup and Relationship with multiple columns - ms-access

I am completely new to Access, but I've done the tutorials, and have some VBA experience with Excel, so I shouldn't be hopeless.
I haven't progressed to forms yet, right now I'm focusing on getting the tables defined and populated, and relationships defined.
I've changed the actual tables in the example here, but the context and problem hold.
Table 1 is Food. Other than the autofield key, it has two fields
FoodCat FoodType
Fruit banana
Fruit apple
Fruit pear
Meat lamb
Meat beef
Meet Chicken
Vegetable Broccoli
etc....
This table is used by another table, in a lookup and relationship setup.
It is easy to set it up so the other table has a field that is restricted to entries with the items in the FoodCat Field (although it is repetitive). I can also restrict the next field to entries with the FoodType Field, but this gives me all the choices.
What I'd like to do, in the new table, is restrict the FoodType choice to the entries that have a matching FoodCat choice.
So, if the item selected on the new table under FoodCat is Meat, I only want the FoodType choices to be lamb, beef, or chicken.
Is this even possible within the table? Do I need to use Forms to get this done?

Answering to your comment:
When you use "Lookup" fields" you are forcing a new relation between the tables.
The best way to avoid the problems listed in the Ten Commandments of Access (specifically: The evils of the lookup fields in tables ) is to create the relations manually, and then use them to create the adequate "lookup" control in a form or report.
Let's say you have the following tables:
tblCategories
id | catName
---+-----------
1 | Fruit
2 | Meat
3 | Vegetable
tblFood
id | idCat | foodName
---+-------+-------------
1 | 1 | Apple
2 | 1 | Banana
3 | 2 | Lamb
4 | 2 | Beef
5 | 3 | Broccoli
In this example is obvious that there's a one to many relation between these two tables, and that the idCat field in tblFood is a foreign key. You can create this relation by hand in the "Relations" window.
With the following query you can get both the foodName and catName fields properly (a good thing to build reports):
select f.*, c.catName
from tblFood as f
inner join tblCategories as c on f.idCat = c.id;
This would throw something like this:
id | idCat | foodName | catName
---+-------+----------+------------
1 | 1 | Apple | Fruit
2 | 1 | Banana | Fruit
3 | 2 | Lamb | Meat
4 | 2 | Beef | Meat
5 | 3 | Broccoli | Vegetable
which is a nice and useful query that you can use in a report... without the need of using Combo Boxes in the report.
So: How on earth to build a control, for example, a ComboBox, that filters only the foodName values depending on a catName value?
First: Create the form
Then: Create a Combo Box and put this in the RowSource property:
select id, catName from tblCategories
Set the control to have two columns, and column widths: 0, 10. This will make the id column in the drop-down list "invisible". Be sure to know the name of this combo box (let's say it is named comboBox01).
Now, create a second combo box, keep the RowSource property empty, and set the column widths to 0, 10. Also be sure to know the name of this second combo box (let's say it is named comboBox02).
And now let's make VBA do what you need: On the properties sheet of the comboBox01 control, look for the afterUpdate event, clic on the ellipsis button, select "VBA code" and write the following
Sub comboBox01_afterUpdate() ' This is added automatically by the VBA editor
strSQL = "select id, foodName from tblFood where idCat=" & comboBox01.Value
comboBox02.rowSource = strSQL
comboBox02.Requery
End Sub ' This is added automatically by the VBA editor
"Lookup controls" (no "lookup fields") are very useful when used in forms. They can save a lot of headaches to the users of your database (you included). But I strongly recommend you to avoid creating them directly in the tables.
Hope this helps.

Yes, it is possible to do within the table. However, it's easier to do through a form and it's more practical to do through a form. You NEVER, EVER want your user interacting directly with a table.

Related

how do i update a one to many map table?

the first is the sectors table that has an id and sector name like this
id | sector
1 | Government
2 | Education
The second is the employee table like this (simplified)
Id | name
1 | sam
2 | tom
Finally I have a sectorMap table (this is used to join the two tables above together) like this
Id | sectorid | employeeid
1 | 1 | 2
2 | 1 | 1
3 | 2 | 2
So in this instance, once I join everything together and view the sectors or each employee, it would show that tom has two sectors (government, education) and sam only has one (government)… hope that makes sense
My question is, within my application, the user has the ability to change these sectors by selecting from a multiple selection dropdown in html. For some reason I thought that by doing an update on duplicate expression would work, however seeing how I have multiple rows of data, I would need to delete all rows within the sectormap table that do not reflect the new selection and contain the selected employees id. What would be the best way of going about that?
For instance, in this case, lets say I open the application and see that tom has two sectors tied to him (government, education) and I only wanted him to have one (government). When I deselect education and select GO. The application returns a list to the server that contains (‘government’). How can I formulate an expression to delete the education sector row from the sectormap table that contains his id?
Your answer is in your question.
1st when you are deselecting education. You will get data of (‘government’). right?
So just invert your query. select those records which is not (‘government’), those are education.
So, education records are you can delete.
Hope this will help you. thanks:)

How to extract relational data from a flat table using SQL?

I have a single flat table containing a list of people which records their participation in different groups and their activities over time. The table contains following columns:
- name (first/last)
- e-mail
- secondary e-mail
- group
- event date
+ some other data in a series of columns, relevant to a specific event (meeting, workshop).
I want to extract distinct people from that into a separate table, so that further down the road it could be used for their profiles giving them a list of what they attended and relevant info. In other words, I would like to have a list of people (profiles) and then link that to a list of groups they are in and then a list of events per group they participated in.
Obviously, same people appear a number of times:
| Full name | email | secondary email | group | date |
| John Smith | jsmith#someplace.com | | AcOP | 2010-02-12 |
| John Smith | jsmith#gmail.com | jsmith#somplace.com | AcOP | 2010-03-14 |
| John Smith | jsmith#gmail.com | | CbDP | 2010-03-18 |
| John Smith | jsmith#someplace.com | | BDz | 2010-04-02 |
Of course, I would like to roll it into one record for John Smith with both e-mails in the resulting People table. I can't rule out that there might be more records for same person with other e-mails than those two - I can live with that. To make it more complex ideally I would like to derive a list of groups, creating a Groups table (possibly with further details on the groups) and then a list of meetings/activities for each group. By linking that I would then have clean relational model.
Now, the question: is there a way to perform such a transformation of data in SQL? Or do I need to write a procedure (program) that would traverse the database and do it?
The database is in MySQL, though I can also use MS Access (it was given to me in that format).
There is no tool that does this automatically. You will have to write a couple queries (unless you want to write a DTS package or something proprietary). Here's a typical approach:
Write two select statements for the two tables you wish to create-- one for users and one for groups. You may need to use DISTINCT or GROUP BY to ensure you only get one row when the source table contains duplicates.
Run the two select statements and inspect them for problems. For example, it's possible some users show up with two different email addresses, or some users have the same name and were combined incorrectly. These will need to be cleaned up in order to proceed. There is great way to do this-- it's more or less a manual process requiring expert knowledge of the data.
Write CREATE TABLE scripts based on the two SELECT statements so that you can store the results somewhere.
Use INSERT FROM or SELECT INTO to populate the tables from your two SELECT statements.

PHP/MySQL - mapping table with 3 (not 2 as usually) columns to inherit permissions

Making CMS to manage restaurants. Briefly, there are restaurants that have their own divisions. Also, there are meals that need to be assigned to a restaurant (so all its divisions can see those meals) or individual division(s) (so only selected division(s) can see meals).
So I created tables:
restaurant_id | restaurant_name
1 | Restaurant 1
2 | Restaurant 2
division_id | restaurant_id | division_name
1 | 1 | 1-1
2 | 1 | 1-2
3 | 2 | 2-1
4 | 2 | 2-2
meal_id | meal_name
1 | Steak
Also created mapping table meals_to_restaurants_divisions that contains 3 columns - meal_id, restaurant_id, division_id
So, if I want to assign meal to Restaurant 1 and ALL its divisions, I would create record:
meal_id | restaurant_id | division_id
1 | 1 | null
If I want to assign meal only to division 2-2, I would create a record:
meal_id | restaurant_id | division_id
1 | null | 4
Could someone advise if such a scheme is correct? How could it be improved? I know someone will say I should only create mapping table with 2 records - meal_id and division_id and assign meal to all divisions instead of assigning to a restaurant, but here's the catch: if Restaurant 1 gets new division created in future, I want new division to inherit the same permissions (so if existing meal is assigned to a restaurant instead of division, all future divisions will inherit restaurant's permissions). Otherwise, I would need to manually edit every meal and assign a new division to it.
If someone is interested why I use null in restaurant_id in 2nd example, it's because if division's parent is changed later (division is assigned to another restaurant), I don't need to scan mapping table and change restaurant_id value there.
To evaluate if your model is correct, the most important aspect is that it fulfills all requirements. Since your description is not complete, we cannot verify that for you. You may e.g. check if devisions can belong to several restaurants at the same time. Or if you have other attributes for devisions (e.g. staff assigned to a devision, the order history, outstanding royalties or ratings on your website), that change or do not change when you move a devision to another restaurant. You could also think of that process as creating a new devision inside another restaurant and assigning all meals to the new devision (or maybe several devisions). It is more a conceptional question than a formal one, and if it is correct (and also if there is a better one) will depend on the requirements.
Formally, your model is correct, as long as you never set both restaurant_id and division_id in your "permission" table, because such an entry would not make any sense. (And as long as restaurant_id is not part of the key in your devision table, which is not the case according to your description).
Your table is basically a flattened 2-level-tree with some implicit conditions. A more general tree could look like
id | parent
---+-------
1 | null -- restaurant "1" (has no parent)
2 | 1 -- devision "1-1"
3 | 1 -- devision "1-2"
4 | null -- restaurant "2"
5 | 4 -- devision "2-1"
6 | 4 -- devision "2-2"
In this tree, a restaurant would be treated like a normal devision (or a devision would be like a sub-restaurant), and you could assign meals to just that id. If you want to assign meal 1 to restaurant 1 and all its divisions, you would create the record meal=1, id=1. If you want to assign meal 1 only to division "2-2", you would create a record meal=1, id=6.
It implicitly prevents you from a situation where you would assign both restaurant_id and division_id to a meal (which is the mentioned condition in your model), as such a combination does not exist anymore. You "flattened" the tree by moving the parents into the restaurant_id and the (1st-level-)children to the devision_id-column of your meals_to_restaurants_divisions-table.
The tree will not enforce that a restaurant cannot belong to another restaurant or that you cannot have sub-sub-devisions. Basically, you treat restaurants explicitly NOT as a special kind of devision (or vice versa).
So both models, while formally correct, have a lot a implicit conditions that they automatically enforce (like the maximum depth in your model), that you would have to enforce manually (like not setting both columns in your model, or the maximum depth in the tree) or that are not supported (like subdivisions in your model). You will have to compare that to your requirements.
A site note: a tree is actually a bad model for hierarchical data in a database, as it gets complicated to (recursively) query several levels deep, and there are better models. I just used it for simplicity - and since you only have 1st-level-children, this restriction does not apply in your case.

DB structure - form with dynamic number of options

I've been reading similar questions, but I think my case is a bit more complicated.
I have a form that register items. These items may have options with sub-options (checkboxes and radio buttons):
The number of checkboxes and radio buttons may decrease/increase but the real pain to design a good structure is for the checkboxes, as these must have (at least I think so) a fixed name column for each one.
The case for radio buttons is easier as I just assign an id to each one (and save the names in a different table).
My current DB structure is simple (between parenthesis is the table/column name):
The items table (item) have columns of type integer (to save the id of the radio buttons).
Another table for the checkboxes (item_option), with columns of type integer (1 if checked, 0 if unchecked). And 1 PK column (item_id) that points to the PK column (id) of the items table.
And tables (again item_option) for the names of the radio buttons with a PK column (id) that points to the option column (is this understandable? Sorry for my bad english).
I think a different table containing the sub-options is better than put all the columns in the main table, right?
So, the radio buttons are stored in the main table (1 column per option) and the checkboxes in a separeted table (1 table per option):
Items table:
+-----+----------+----------+
| id | Option_1 | Option_2 |
+-----+----------+----------+
| 123 | 3 | 1 |
+-----+----------+----------+
| 456 | 2 | 3 |
+-----+----------+----------+
| 789 | 1 | 2 |
+-----+----------+----------+
item_option_3 table (this would be needed to know which ones are checked):
+--------------+--------------+--------------+---------+
| Sub_Option_1 | Sub_Option_2 | Sub_Option_3 | item_id |
+--------------+--------------+--------------+---------+
| 1 | 0 | 1 | 123 |
+--------------+--------------+--------------+---------+
| 1 | 1 | 0 | 456 |
+--------------+--------------+--------------+---------+
| 0 | 1 | 1 | 789 |
+--------------+--------------+--------------+---------+
item_option_1-2 table (this would be used to print the names):
+-----------+--------------+--------------+
| option_id | name | name_es |
+-----------+--------------+--------------+
| 1 | Sub_Option_1 | Sub_Opción_1 |
+-----------+--------------+--------------+
| 2 | Sub_Option_2 | Sub_Opción_2 |
+-----------+--------------+--------------+
| 3 | Sub_Option_3 | Sub_Opción_3 |
+-----------+--------------+--------------+
What kind of structure do I need to spawn these sub options (checkboxes) dynamically?
What about something like this?
Your model has option keys as columns and values as rows. Why have both keys and values be rows? If you don't need complex type-based validation, it should suffice to have a single options table with a one to optionally many relationship to itself to account for suboptions. To enumerate all options and values, just retrieve all rows from the table. If ParentOptionId is null, then it is a base-level option; otherwise it is a suboption.
UML & ER version below.
EDIT: After reading through your question and comments again, I've come up with a more complicated but more robust design for you to consider:
It works like this:
Every user input is an Option. Every option consists of a display text (OptionText), tooltip/subtext/etc (Description), a default and then user supplied value (Value), a value type (ValueType boolean,text, date, etc). It also has a DisplayOrder so you know where to situate it in relation to other Options in its group. Options can also have a parent/child relationship with other Options. You can do the same for the other entities if you want but I did not model that.
Every Option is contained within an OptionGroup with 0 or more sibling Options. OptionGroups are just a collection of one or more related Options. The GroupType field dictates how your form builder needs to treat that group. The most obvious example would be for your radio button groups; each of those would be an OptionGroup and each radio button would be a boolean Option within the OptionGroup. An OptionGroup could just as easily handle a multiple selection checkbox group or just some related text inputs that need a common header text (like a street address).
For further dynamic design OptionGroups are contained within GroupSections, even if there is just one default GroupSection in a form.
Finally, a Form models your final actual UI form and consists of one or more GroupSections.
This should be flexible enough for you to tweak to your liking. What do you think?
Final note: if you are looking into dynamically building your forms in Javascript, check out a few frameworks like X-editable or formly. They take JSON or configuration objects and build out the entire form with validation/etc from there while giving you some hooks for event handling. Chances are you don't need to completely reinvent the wheel unless you want to keep your implementation as simple and specific as possible.

Related Key/Value table indexing / search

I have table 'elements' that is related with table 'element_parameters'. element_parameters table have key/value structure. Keys and values are dynamicaly, they can be created be user or by some software, so I can't predefine them in 'elements' table.
For example I have elements 'flower' and 'car':
elements
--------
flower
car
element_parameters
------------------
element | key | value
flower | smell | soft
car | manufacturer | fiat
flower | color | red
car | wheels | 4
As you can see, there could be any keys and any values.
But often I need to find elements by their parameters. This is the problem. One element could have 10000+ parameters. So if I have 100 elements, I have to search through 1000000 parameters each time i want to find some element. And i can't do this in one query, be cause first I have to find all parameters thats fits my condition, group them by parameter ID and then search elements table for those ID's.
Is there some search engines, where I could merge and index elements with their parameters to 'one row'? Elasticsearch would be good decision for this situation? Maybe there is other ways to solve it?
Thank you.
I think you should modify your db like this:
elements
-----------
id | name
1 | flower
2 | car
element_parameters
-------------------------------------------------
element_id | parameters
1 | {"color":"red","smell":"soft"}
2 | {"manufacturer": "fiat", "wheels":3}
You can find easily any element's parameter:
$id = 1;
$element = Element::find($id)->load('ElementParameters')->get();
$paremeters = json_decode($element->ElementParameters);