One or four tables? (db structure) - database

Items are connected to:
one or more "region" and/or
one or more "county" and/or
one or more "city" and/or
one or more "place".
My question is how I should set up the relations:
id | thingID | regionId | countyId | cityId | placeId
or
4 tables?
id | thingId | regionId
id | thingId | countyId
id | thingId | cityId
id | thingId | placeId
or is there perhaps another better solution?

I may be overthinking this, but I think there's probably a relationship between "region", "county", "city" and "place" - an item that belongs to a "place" should also belong to the city, county and region.
You can solve this in both the designs you provide - but you need a fair amount of additional logic. In the first solution, you need to make sure that every time you insert a record, you populate the location from "left to right" - a record with only "place" is not valid.
In the second solution, you need to populate all relevant rows - an item in Chelsea must also have records for London, Middlesex and South East England.
There's another way...
Table: location
ID Name Parent
------------------------
1 South East England null
2 Middlesex 1
3 London 2
4 Chelsea 3
5 Kent 1
6 Canterbury 5
Table: item
Id name
-----------------
1 Posh Boy
2 Cricket ground
3 Rain
Table: item_location
ItemID LocationID
--------------------
1 4 //Posh boy in Chelsea
2 2 // Cricket ground in Middlesex
3 1 // Rain in the South East of England.

The second option is clearly better. It's a many-to-many relationship for each of these categories, and that's what the second option describes.
The first option would result in some very odd data. If you had a ThingId that was associated to all of the different types once, you would have one row that had all the columns filled in. Then if your ThingId needed to be tied to an additional city, you would have another row that had only the cityId filled in, with the other columns remaining null.
A table design that results in a lot of null values is usually (not always) a sign that your model is flawed.

Related

SQL column which is a list containing other rows

I have a table which looks like this:
Persons
| Id | Name | FavoriteColor |
And I want to add a new column which is "Friends" so that it becomes
Persons
| Id | Name | FavoriteColor | Friends |
I want the Friends column to be (in abstraction) a list containing the Ids of other rows in the Persons table.
What's the best way to do this? I know I can use FK's to link up tables, but I'm not just linking a specific row to a specific row in a different table, but rather a specific row to a specific table.
You dont add a field, you create a second table
Persons: id, Name, Favorite Color
Friends: PersonA_id, PersonB_id
Where PersonA_id, PersonB_id are Foreign Key to Persons table.
So you can have things like this in persons
id Name Color
1 Luis Blue
2 Pedro Red
3 Ana Yellow
4 Donald Black
Friends:
PersonA_id PersonB_id
1 2
3 1
Luis have 2 friends, Pedro and Ana only have a friend (Luis), and Donald 0 friends.

Single table column refers to multiple primary key

I need to store multiple values in a single column.
For example I am creating table which holds the user preferences
e.g.
| user_id | cities | countries |
|---------|------------|------------|
| 1 | 10, 11, 23 | 21, 34 |
because i can't store them as array (or don't prefer to store as array even if it is available - due to maintenance and performance reasons - and better RDMS design), i have to create a mapping table like this
| user_id | type | reference_id |
|---------|---------|--------------|
| 1 | CITY | 10 |
| 1 | CITY | 11 |
| 1 | CITY | 23 |
| 1 | COUNTRY | 21 |
| 1 | COUNTRY | 34 |
The reference id in this column refers to the master tables like city, country, etc.
The problem here i see is
I can't have FK reference to city or country table, because single reference_id column may refer to city or country depends on the type
As i can't have FK, there is no guaranty that we can't have dirty data
Is there any better approach?
Note:
I have given city/country as sample, but i need to have around 20 columns which can have multiple values like city or country
In future i may introduce some boolean preference like "whether you like to travel" so i might want to store TYPE as "TRAVEL" and referece_id as 0 for yes 1 for no; which definately will not have any reference
You could create a Location Table {LocationId, locationType (city/country)}
and then everytime you add a new record to the city or country table, add it to location table first, then add it to city (or country) table as appropriate with same cityId (or countryId) as was used as LocationId in Location Table.
then create FK between preferences table and location table, and add [zero or one] to one (0/1 - 1) FK relationship between City and country tables to the Location table. (Every record in City and COuntry table tables must be in Location table, but not the other way around.
You're saying you want a table for generic data instead of 20 lookup tables enforcing RI? On a large system, the data would be stored in multiple tables instead of using a delimiter to separate the values and then exploding them out in another table, introducing the problem of enforcing RI. If you're storing values that are really generic, like code/description pairs, you just need a codeSetID field to identify which codes belong in which codesets.

SQL Server table identity specification and composite key

hi I have two basic tables one is company and the next one is items reationship between these two tables are 1 to M (1 company has many items associated with it and one item belongs to one company only )
Company = {companyid,companyname}
_________
items = {itemid,itemname,companyid}
_______ ---------
I have set itemid identity specification to YES and now the item ID gets increased
if I have two companies id 1 & 2 A sample data table would show this
itemid itemname idcompany
----- ------- ---------
1 car 1
2 bus 2
3 bike 1
4 motorcycle 2
My issue is when showing company specific data I get this
company 1
itemid itemname idcompany
----- ------- ---------
1 car 1
3 bike 1
company 2
itemid itemname idcompany
----- ------- ---------
2 bus 2
4 motorcycle 2
how do I keep the item id sequential for each company ?
Thank you
Question
What does "sequential" even mean?
Suggestion
The Sequence possibly could change based on the business question. For instance, does sequence always mean in the order in which the row was inserted into the table, or does it mean the time at which the item was added? Regardless, you may want to implement the concept of a sequence independent of how the data is stored. For instance, based on your need, you could do something like this (which gives you the sequence of each item by company, based solely on the item_id itself):
select *,
itemsequence = row_number() over (
partition by (idcompany)
order by (itemid))
from items;
Hope this helps.

Database schema for product quantity

I have some issues with creating database schema for a following scenario:
Shop, where you configure your order. Let's say user orders flowers and chocolate. So far I had the following structure:
OrderID FK_Flower FK_Chocolate
1 1 1
Where FK's pointed to the entry in database such as:
Id Name Price
1 Rose 100
The same for chocolate.
However now, there is a change: use can order multiple different flowers. So let's say, he can order 5 Roses, 3 Daisies.
What changes should I make, to solve this issue?
You want a many-to-many relationship.
Change the Orders table to something like this:
Orders:
-------
Id
1
The Flowers table stays the same:
Flowers:
------------------
Id Name Price
1 Rose 100
2 Daisy 120
Create a new table with with the Order and Flower ID's as foreign keys:
Orders_Flowers:
-------------------------
FK_Order_Id FK_Flower_ID
1 1
1 1
1 1
1 1
1 1
1 2
1 2
1 2
This way, the Order with Id = 1, has 5 Roses and 3 Daisies.

Adding multiple entries to table

I've got a website where users can make recipes.
So I've got a table called ingredients with ingredients
So the user selects the ingredients he/she wants with the amount required, and then I will store this in a new table called recipes
But I wonder what's the best practice for storing this
I was thinking like this
RECIPES
Id | UserId | IngredientId
--------------------------
0 | 23 | 3,6,7,9,2,1
1 | 56 | 8,2,6,7,1
2 | 80 | 1,7,3,2,7
3 | 11 | 6,7,4,3,21,2
You may consider having join tables. It would work something like this:
User
Id | Name
0 | Bob Smith
1 | Susie Jones
Recipe
Id | Name
0 | Ramen
1 | Pizza
Ingredient
Id | Name
0 | Flour
1 | Water
2 | Yeast
User_Recipe
User_Id | Recipe_Id
0 | 1
1 | 0
Recipe_Ingredient
Recipe_Id | Ingredient_Id | Quantity
1 | 0 | 1 C.
1 | 1 | 1/2 C.
1 | 2 | 1 T.
It depends on how complex your application is. Your table is not normalized as you have written it. On the other hand, my way might be an overkill for a small application, but I would propose the following schema:
Table users
This table contains your user information and each row has a unique user id (as I understand you already have this)
Table ingredients
Here you store your ingredients that also have a unique id. Also, this does not contain any recipe information like quantity but instead has only ingredient attributes like: name, description, form, price_per_kilo, etc.
Table recipes
This table is a many-to-many relationship between users and recipes. Again, it contains only recipe attributes like: user_id, name, date_created, rating, difficulty, instructions, etc
Table recipe_ingredients
Finally, this table lists all the ingredients a recipe requires, including the amount. Columns would be recipe_id, ingredient_id, amount, unit, comment, etc
Hope it helps

Resources