SQL - Select data from three tables where one table has multiple foreign keys to the same primary key - sql

I have the following tables and relations:
When I create a User, that user gets a CurrentWeekrow and that current week row in turn gets a CurrentWeekStatusrow. The user can add food items to the Foodtable and then can choose from these food items and select a few to insert in CurrentWeek.
In the client I want to grab CurrentWeekas an object that has a list of Foodobjects and a list of their corresponding status.
I am struggling as to how to make this happen. I think this can be done by making multiple queries to the database, one to fetch CurrentWeek and then from this extract all the FoodId's and make separate queries to fetch each Food. But this seems like a very bad solution.
The other solution I can think of is making a view with all the necessary data. But I don't know how to make this view and even if I manage to make the view I don't know how to separate each Food into different objects.
Do anyone know of a good way to accomplish this?
I use NodeJs as a REST API and Android Studio with retrofit to send REST calls.

After consulting StackOverflow and a few colleagues I changed the initial database schema into:
This was a design I initially chose to not go with as I thought adding one row on the CurrentWeek table for each user would be better than to add many rows for each user in the PlannedFood table. I see now however that this design have a few advantages as compared to the other design.
Designing it this way also solves my initial question as I can now grab all the rows in PlannedFood for a specific user, joining on FoodId and then map the Food data into a Foodobject on client-side.

Related

How can I replicate many to many relationship

I have a product database where I am trying to replicate a particular product's data and relationships to a new product, a clone. I am puzzled however on how to replicate several many to many relationships. For example, consider a product with two parts, and for each part, their are several colors available. I have a Product table, a product Areas table, and a Colors table. The product id is a foreign key in the area table, one to many. The Area table has an area id (pk) along with other descriptive fields, and the Colors have color ids (pk) along with palette information. A fourth table serves as the many to many look up table, it's primary key being the part id and the color id combined. This is a pretty straight forward configuration as far as it goes.
I can't think of a way to clone this structure, however, despite many approaches which would be way too much to elaborate upon here. I can easily enough replicate the left hand, product-area relationship, generating new AreaIDs (A,B,C). But in a next step, I then want to replicate the many-to-many relationship using the new area ids. However, now I don't know which original ID (H,L,W) to associate with which new ID.
For example, does the new id A get mapped to the set of colors from the old ID H, L, or W? I have only id's to work with. I can select both parts and part-color pairs from the source in one select statement, but I can't insert into two tables with one statement.
In other words, how do I replicate many to many relationships if I want to supply a new ID for half of it? Do I have to resort to cursors? I can if I need to, but I'm imagining there an elegant way to accomplish this that I just can't figure out. Maybe using a temp table or some sort of table valued function? I've tried to search for answers, but I all I can find is advice on setting up many-to-many relationships.
Thanks for you experts who have the patience to read through this question.
SymmetricDS replicates tables that have many into many relationships using change data capture. The key is to perform an initial load to get the databases in sync initially so that if a child record is updated the change data capture will also work. In the latest versions of SymmetricDS (3.10 and higher) it will also auto resolve foreign key errors if the databases are not in sync. If a child row is being loaded to a target without the parent it will callback to the source to load the missing parent as well so that you do not need to intervene.

Custom user defined database fields, what is the best solution?

To keep this as short as possible I'm going to use and example.
So let's say I have a simple database that has the following tables:
company - ( "idcompany", "name", "createdOn" )
user - ( "iduser", "idcompany", "name", "dob", "createdOn" )
event - ( "idevent", "idcompany", "name", "description", "date", "createdOn" )
Many users can be linked to a single company as well as multiple events and many events can be linked to a single company. All companies, users and events have columns as show above in common. However, what if I wanted to give my customers the ability to add custom fields to both their users and their events for any unique extra information they wish to store. These extra fields would be on a company wide basis, not on a per record basis ( so a company adding a custom field to their users would add it to all of their users not just one specific user ). The custom fields also need to be sesrchable and have the ability to be reported on, ideally automatically with some sort of report wizard. Considering the database is expected to have lots of traffic as well as lots of custom fields, what is the best solution for this?
My current research and findings in possible solutions:
To have generic placeholder columns such as "custom1", "custom2" etc.
** This is not viable as there will eventually be too many custom columns and there will be too many NULL values stored in the database
To have 3x tables per current table. eg: user, user-custom-field, user-custom-field-value. The user table being the same. The user-custom-field table containing the information about the new field such as name, data type etc. And the user-custom-field-value table containing the value for the custom field
** This one is more of a contender if it were not for its complexity and table size implications. I think it will be impossible to avoid a user-custom-field table if I want to automatically report on these fields as I will have to store the information on how to report on these fields here. However, In order to pull almost any data you would have to do a million joins on the user-custom-field-value table as well as the fact that your now storing column data as rows which in a database expected to have a lot of traffic as well as a lot of custom fields would soon cause a problem.
Create a new user and event table for each new company that is added to the system removing the company id from within those tables and instead using it in the table name ( eg user56, 56 being the company id ). Then allowing the user to trigger DB commands that add the new custom columns to the tables giving them the power to decide if it has a default value or auto increments etc.
** Everytime I have seen this solution it has always instantly been shut down by people saying it would be unmanageable as you would eventually get thousands of tables. However nobody really explains what they mean by unmanageable. Firstly as far as my understanding goes, more tables is actually more efficient and produces faster search times as the tables are much smaller. Secondly, yes I understand that making any common table changes would be difficult but all you would have to do is run a script that changes all your tables for each company. Finally I actually see benefits using this method as it would seperate company data making it impossible for one to accidentally access another's data via a potential bug, plus it would potentially give the ability to back up and restore company data individually. If someone could elaborate on why this is perceived as a bad idea It would be appreciated.
Convert fully or partially to a NoSQL database.
** Honestly I have no experience with schemaless databases and don't really know how dynamic user defined fields on a per record basis would work ( although I know it's possible ). If someone could explain the implications of the switch or differences in queries and potential benefits that would be appreciated.
Create a JSON column in each table that requires extra fields. Then add the extra fields into that JSON object.
** The issue I have with this solution is that it is nearly impossible to filter data via the custom columns. You would not be able to report on these columns and until you have received and processed them you don't really know what is in them.
Finally if anyone has a solution not mentioned above or any thoughts or disagreements on any of my notes please tell me as this is all I have been able to find or figure out for myself.
A typical solution is to have a JSON (or XML) column that contains the user-defined fields. This would be an additional column in each table.
This is the most flexible. It allows:
New fields to be created at any time.
No modification to the existing table to do so.
Supports any reasonable type of field, including types not readily available in SQL (i.e. array).
On the downside,
There is no validation of the fields.
Some databases support JSON but do not support indexes on them.
JSON is not "known" to the database for things like foreign key constraints and table definitions.

Relational Table design

I am designing a feature for a database, but I am stuck on design.
I have a table called AgendaItems, this table is a table with Agenda Items that could be assign to possible multiple users.
Users is a table that contains a record of user names, containing a fixed amount of 17 names.
How would I design these tables possibly another table that keeps track of who is working on what Agenda Item. Keep in mind multiple users could work on an agenda Item and users could work on multiple items.
I am not sure who to design this, and wondering if it would even work?
Thanks
I don't know if I understood your problem but I think your relationship is N-N.
So, you need to create another table (UsersAgendaItems). This table must contain the AgendaItems ID and Users ID, where both of then are FK.
Your PK could be a composite PK. This way you can know what user is related with what AgendaItems.
But I don't know if that is what you want. If this is not your case, please, try to explain a little bit more!
Thanks!

What is the most correct way to store a "list" in a SQL Database?

So, I've read a lot about how stashing multiple values into one column is a bad idea and violates the first rule of data normalisation (which, surprisingly, is not "Do Not Talk About Data Normalisation") so I need some help.
At the moment I'm designing an ASP .NET webpage for the place I work for. I want to display data on a web page depending on what Active Directory groups the person belongs to. The first way of doing this that comes to mind is to have a table with, essentially, a column containing the AD group and the second column containing what list of computers belong to that list.
I've learnt that this is showing great disregard for relational databases, so what is a better way to do it? I want to control this access by SQL tables, so I can add/remove from these tables and change end users access accordingly.
Thanks for the help! :)
EDIT: To describe exactly what I want to do is this:
We have a certain group of computers that need to be checked up on, however these computers are in physically difficult to reach locations. The organisation I belong to has remote control enabled for these computers, however they're not in the business of giving out the remote control password (understandable).
The added layer of complexity is that, depending on who you are, our clients should only be able to see a certain group of computers (that is, the group of computers that their area owns). So, if Group A has Thomas in it, and Group B has Jones in it, if you belong to either group then you would just see one entry. However, if you belong to both groups you should see both Thomas and Jones computers in it.
The reason why I think that storing this data in a SQL cell is the way to go is because, to store them in tables would require (in my mind) a new table for each new "group" of computers. I don't want to crank out SQL tables for every new group, I'd much rather just have an added row in a SQL table somewhere.
Does this make any sense?
You basically have three options in SQL Server:
Storing the values in a single column.
Storing the values in a junction table.
Storing the values as XML (or as some other structured data format).
(Other databases have other options, such as arrays, nested tables, and JSON.)
In almost all cases, using a junction table is the correct approach. Why? Here are some reasons:
SQL Server has (relatively) lousy string manipulation, so doing something as simple as ensuring a unique list is really, really hard.
A junction table allows you to store lots of other information (When was a machine added? What is the full description of the machine? etc. etc.).
Most queries that you want are pretty easy with a junction table (with the one exception of getting a comma-delimited list, alas -- which is just counterintuitive rather than "hard").
All the types are stored natively.
A junction table allows you to enforce constraints (both check and foreign key) on the elements of the list.
Although a delimited list is almost never the right solution, it is possible to think of cases where it might be useful:
The list doesn't change and presentation of the list is very important.
Space usage is an issue (alas, denormalization often results in fewer pages).
Queries do not really access elements of the list, just the entire thing.
XML is also a reasonable choice under some circumstances. In the most recent versions of SQL Server, this can be made pretty efficient. However, it incurs the overhead of reading and parsing XML -- and things like duplicate elimination are still not obvious.
So, you do have options. In almost all cases, the junction table is the right approach.
There is an "it depends" that you should consider. If the data is never going to be queried (or queried very rarely) storing it as XML or JSON would be perfectly acceptable. Many DBAs would freak out but it is much faster to get the blob of data that you are going to send to the client than to recompose and decompose a set of columns from a secondary table. (There is a reason document and object databases are becoming so popular.)
... though I would ask why are you replicating active directory to your database and how are you planning on keeping these in sync.
I not really a bad idea to store multiple values in one column, but will depend the search you want.
If you just only want to know the persons that is part of a group then you can store persons in one column with a group id as key. For update you just update the entire list in a group.
But if you want to search a specified person that belongs to group, then its not recommended that you store this multiple persons in one column. In this case its better to store a itermedium table that store person id, and group id.
Sounds like you want a table that maps users to group IDs and a second table that maps group IDs to which computers are in that group. I'm not sure, your language describing the problem was a bit confusing to me.
a list has some columns like: name, family name, phone number etc.
and rows like name=john familyName= lee number=12321321
name=... familyname=... number=...
an sql database works same way. every row in a sql database is a record. so you jusr add records of your list into your database using insert query.
complete explanation in here:
http://www.w3schools.com/sql/sql_insert.asp
This sounds like a typical many-to-many problem. You have many groups and many computers and they are related to eachother. In this situation, it is often recommended to use a mapping table, a.k.a. "junction table" or "cross-reference" table. This table consist solely of the two foreign keys in your other tables.
If your tables look like this:
Computer
- computerId
- otherComputerColumns
Group
- groupId
- othergroupColumns
Then your mapping table would look like this:
GroupComputer
- groupId
- computerId
And you would insert a single record for every relationship between a group and computer. This is in compliance with the rules for third normal form in regards to database normalization.
You can have a table with the group and group id, another table with the computer and computer id and a third table with the relation of group id and computer id.

Delimited string of ids as a field or a separate table?

I have a database in which I store a large amount of user-created products.
The user can also create "views" which works as a container holding these products, lets call them categories.
It would be simple if each product had a category-field containing the id of the category, however each product can be added to multiple categories so that doesn't work.
Presently I solve this by having a string-field "products" in the category-table which is a comma-separated list of product-ids.
What I'm wondering is basically if it's "okay" to do it this way? Is it generally accepted? Will it cause some kind of problem I'm not realizing?
Would it be better to create another table named something like productsInCategories which has 2 fields, one with a category-id and one with product-id and link them together this way?
Will one of these methods perform better or be better in some other way?
I'm using sqlce at the moment if that matters, but that will most likely change soon.
I would go for the second option: a separate table.
Makes it easier to handle if you need to query from the product perspective. Also the join to the categories will be simple and fast. This is exactly what relational databases are made for.
Imagine a simple query like what categories a product is in. With your solution you need to check all categories one by one, parse the csv-list of each category to find the products. With a separate table it is one clean query.