select `one` where location = one, all or multiple choices - mysql

I have multiple creatures in database(mysql) and 6 different areas. Currently all creatures appear in everywhere, but I would like to make some appear in one location or multiple selected locations.
The way I would solve it right now is that every location has id from 1 to 9. Graveyard = 1, Swamp = 2, Forest = 3, Caves = 4. Then have it in the creatures table saved as field where_creature_appears
where
12 appears only in Graveyard and Swamp;
23 appears only in Swamp and Forest;
124 appreas only in Graveyard, Swamp, Caves;
etc
and with sql I would use WHERE LIKE % $location_id %. If I have more locations then I could extend to letters as well.
Question is would there be better way to do it, or simpler, or smarter. Happy if someone can point in the useful direction with links or ideas.
Thanks for any help!

You can do it by having one more table that would be many-to-many table.
Basically, in that table you will have the information if that creature is in that specific area and the opposite. Because, many creatures can be in many areas, and many areas can have many different creatures.
That table should look like this:
Table name: creature_area
creature_id | area_id
----------------------
1 | 2
1 | 3
3 | 2
5 | 1
Then, you will be able to query all the areas for the specific creature, and also all the creatures for the specific area, like this:
Give me IDs of all areas for this creature is in:
SELECT area_id FROM creature_area WHERE creature_id = ....
Give me IDs of all creatures that are in this area:
SELECT creature_id FROM creature_area WHERE area_id = ....
Then you can do all kind of JOINs to get the names of those creature/areas and such.
More details on how to achieve this is here: https://dzone.com/articles/how-to-handle-a-many-to-many-relationship-in-datab
I hope this helps.

Related

Better to have one master table or split into multiple tables?

I am creating a database and I am unsure of the best way to design my tables. I have a table of real estate properties and I want to store information about those properties - e.g. bedrooms, bathrooms, size... I may have additional information I want to store in the future if it seems useful - e.g. last purchase price or date built, so I need to be flexible to make additions.
Is it better to create a separate table for each "characteristic" or to have one table of all the characteristics? It seems cleaner to separate the characteristics, but easier programming-wise to have one table.
CHARACTERISTIC TABLE
id property_id characteristic value
1 1 bedrooms 3
2 1 bathrooms 2
3 1 square feet 1000
4 2 bedrooms 2
...
OR
BEDROOM TABLE
id property_id bedrooms
1 1 3
2 2 2
...
BATHROOM TABLE
id property_id bathrooms
1 1 2
...
Forgive me if this is a stupid question, my knowledge of database design is pretty basic.
I would suggest a middle ground between your two suggestions. Off the cuff I would do
property table (UID address zip other unique identifying properties)
Rooms table ( UID, propertyID, room type , room size,floor, shape, color, finish, other roo specific details ect..)
Property details (uid, propertyID, lot size, school district, how cost, tax rate, other entire property details)
Finally a table or two for histories eg.
Property sales history(UID, PropertyID , salesdate, saleprice, sale reason, ect..)
Often grouping your data by just "does it match" logic can yield you good results.... care needs only be taken to account for 1to1 and 1tomany relationship needs of tables.
I am focused to this:
"I have a table of real estate properties"
Now as far as i knew you has to be a different type of:
Houses
Bedrooms
Comfort room and so on.
For further explanation:
You has to be a table of:
1. House type
2. House names,description,housetypeid,priceid,bedroomid,roofid,comfortroomid and any other that related to your house.
3. Bedroom type
4. Comfort room type
5. Dining type
6. roof type if it has.
7. House prices
8. Bathroom type
something like that.
One table with a few columns:
Columns for price, #br, #bath, FR, DR, sqft and a small number of other commonly checked attributes. Then one JSON column with all the other info (2 dishwashers, spa, ocean view, etc).
Use WHERE clause for the separate columns, then finish the filtering in you client code, which can more easily look into the JSON.

Storing combinations of item properties in database

I have a problem of such:
Let's say I have an item, a CUP for example. I want to sell it, but want to allow the user to pick CUP properties, such as Size, Color, Material. When the user will select Size (maybe Large), color (maybe Black) and Material (maybe Glass) then I need to show him, that we have 20 such Cups in warehouse and the cost is $25 each. And now: I don't know how to store those combinations in database.
Here is my ultra stupid solution:
For each combination I will have a column, yet, adding any new combination might be painfull as well, as removing some, I will have to map them somehow, well...
Id | Product Name | LargeBlackGlassPrice | LargeBlackGlassCount | SmallBlackGlassPrice | SmallBlackGlassCount | Medium...
stupid idea, but as for now didn't hit anything better :/
Hope it's clear what I want to achieve.
Thank you
Consider the following ERD:
The system administrator maintains a list of product categories, these may include, for example, cups. The administrator also maintains a list of features. These could include size, colour, material, and anything else that they decide is potentially important for any type of product. The administrator can then create an intersection of categories and features to indicate which features matter for a particular product category.
This establishes the "rules" for a catalogue of products. Which types of products do you have and what is important to know about each of these types products.
Now, to store the products themselves, you have the SKU table. Each individual product, for example: Large Black Glass Cups is stored in this table. You can store the current price of this product here. You can also store the stock on hand here, although I've recommended elsewhere to never store stock quantity directly. Inventory management is not the basis of your question, however.
For any particular product (SKU) you then have a list of product features where the specific values of each specific product are stored. The features that matter are the ones defined by the product's category as listed in the CATEGORY_FEATURE table.
On your website, when a customer is searching for items in a PRODUCT_CATEGORY, (e.g. Cups) you show them the list of CATEGORY_FEATUREs that apply. For each feature, you can create a drop down list of possible values to choose from by using:
select distinct PF.value
from CATEGORY_FEATURE CF
inner join PRODUCT_FEATURE PF
on CF.product_category_id = PF.product_category_id
and CF.feature_id = PF.feature_id
where CF.product_category_id = CategoryOfInterest
and CF.feature_id = FeatureOfInterest
order by
PF.value
This design gives your administrator the ability to define new product categories and product features without having to make database schema or code changes.
Many people are likely to point out that this design uses the Entity-Attribute-Value (EAV) pattern, and they are equally likely to point out that EAV is EVIL. I agree in principle that EAV is to be avoided in almost all cases, but I have also asserted that in some cases, and in particular in the case of product catalogues, EAV is actually the preferred design.
Table1 => Cup Master
Fields => Cup Id | Product Name
Example =>
1001 | CUP A
1002 | CUP B
Table2 => Property Master
Fields => Property_Id | Properties
Example =>
1 | LargeBlackGlass
2 | SmallBlackGlass
3 | MediumBlackGlass
Table3 => Inventory Master
Fields => Cup Id | Property_Id | count | price_per_piece
Example =>
CUP A | 1 | 3 | 45/=
CUP A | 2 | 2 | 40/=
CUP A | 3 | 2 | 35/=
CUP A | 1 | 3 | 45/=
CUP A | 2 | 2 | 40/=
NOTE: A cup with a particular property might be available and with other property might not.
Let try to reason how to solve your task. I will describe general conception and split it in some steps:
Define types of products that you are going to sell: cup, plate, pan and so on. Create table products with fields: id, name, price.
Define colours of products: black, red, brown. Create table products_colours with fields: id, name, price.
Define sizes of products: small, medium, large. Create table products_sizes with fields: id, name, price.
In simple case all types of products will have the same price and will store in table products.
In simple case additional price for colours and sizes will be the same for all types of products and will be stored in tables products_colours and products_sizes.
Create table customers_products with fields: id, products_id, products_colours_id, products_sizes_id, quantity.
Write a query for join all table together to fetch all products with colours, sizes and all prices from db.
In the script iterates through all rows and calculate price for every product as a sum of product price, size price and colour price.
To sum up: this is very basic implementation that doesn't include things like brands, discounts and so on. However, it gives you understanding how to scale your system in case of adding additional attributes that affect the final price of products.

database schema one column entry references many rows from another table

Let's say we have a table called Workorders and another table called Parts. I would like to have a column in Workorders called parts_required. This column would contain a single item that tells me what parts were required for that workorder. Ideally, this would contain the quantities as well, but a second column could contain the quantity information if needed.
Workorders looks like
WorkorderID date parts_required
1 2/24 ?
2 2/25 ?
3 3/16 ?
4 4/20 ?
5 5/13 ?
6 5/14 ?
7 7/8 ?
Parts looks like
PartID name cost
1 engine 100
2 belt 5
3 big bolt 1
4 little bolt 0.5
5 quart oil 8
6 Band-aid 0.1
Idea 1: create a string like '1-1:2-3:4-5:5-4'. My application would parse this string and show that I need --> 1 engine, 3 belts, 5 little bolts, and 4 quarts of oil.
Pros - simple enough to create and understand.
Cons - will make deep introspection into our data much more difficult. (costs over time, etc)
Idea 2: use a binary number. For example, to reference the above list (engine, belt, little bolts, oil) using an 8-bit integer would be 54, because 54 in binary representation is 110110.
Pros - datatype is optimal concerning size. Also, I am guessing there are tricky math tricks I could use in my queries to search for parts used (don't know what those are, correct me if I'm in the clouds here).
Cons - I do not know how to handle quantity using this method. Also, Even with a 64-bit BIGINT still only gives me 64 parts that can be in my table. I expect many hundreds.
Any ideas? I am using MySQL. I may be able to use PostgreSQL, and I understand that they have more flexible datatypes like JSON and arrays, but I am not familiar with how querying those would perform. Also it would be much easier to stay with MySQL
Why not create a Relationship table?
You can create a table named Workorders_Parts with the following content:
|workorderId, partId|
So when you want to get all parts from a specific workorder you just type:
select p.name
from parts p inner join workorders_parts wp on wp.partId = p.partId
where wp.workorderId = x;
what the query says is:
Give me the name of parts that belongs to workorderId=x and are listed in table workorders_parts
Remembering that INNER JOIN means "INTERSECTION" in other words: data i'm looking for should exist (generally the id) in both tables
IT will give you all part names that are used to build workorder x.
Lets say we have workorderId = 1 with partID = 1,2,3, it will be represented in our relationship table as:
workorderId | partId
1 | 1
1 | 2
1 | 3

What table structure would best fit this scenario?

I am developing an evaluation system for different programs that needs a lot of flexibility. Each program will have different things to track, so I need to store what data points they want to track, and the corresponding data for the person being evaluated on the particular data point. I am guessing several tables are appropriate. Here is a general outline:
Table: accounts
- unique ID assigned to each account. We'll call this 'aid'
Table: users
- each user with unique ID.
Table: evaluation
- each program will enter in the metrics they want to track into this table (i.e attendance)
- column 'aid' will correspond to 'aid' in account table
Table: evaluation_data
- data (i.e attendance) entered into this database
- column 'aid' will correspond to 'aid' in account table
- column 'uid' will correspond to 'uid' in user table
The input form for evaluation_data will be generated from what's in the evaluation table.
This is the only logical way I can think of doing this. Some of these tables will be growing quite large over time. Is this the most optimal way of doing this?
I'm a little confused about how accounts, users and programs all relate to each other and whether or not account and program are the same thing and that you used the terms interchangeably. I'm going to use different terms which are just easier for me to understand.
Say you have a website that allows freelancers to keep track of different projects and they can create their own data to track. (Hope you see the similarity)
Tables...
freelancers
id title etc
projects
id freelancer_id title description etc
data_options
id freelancer_id title
You can even add other columns like data_type and give options like URL, email, text, date, etc which can be used for validation or to help format the input form.
example data:
1 5 Status
2 5 Budget
3 5 Customer
4 99 Job Type
5 99 Deadline
6 102 Price
7 102 Status
8 102 Due By
This display 3 different freelancers tracking data, freelancers with the id's 5, 99, and 102. Deadline and Due By are essentially the same but freelancers can call these whatever they want.
data_values
id project_id option_id option_value
a column freelancer_id as you would be able to to a join and get the freelancer_id from either the project_id or the option_id
example data:
1000 1 2 $250
1001 1 1 Completed
1002 1 3 Martha Hayes
This is only showing information freelancer with the id 5 has input because option_id's 1-3 belong to that user.

MySQL: How to pull information from multiple tables based on information in other tables?

Ok, I have 5 tables which I need to pull information from based on one variable.
gameinfo
id | name | platforminfoid
gamerinfo
id | name | contact | tag
platforminfo
id | name | abbreviation
rosterinfo
id | name | gameinfoid
rosters
id | gamerinfoid | rosterinfoid
The 1 variable would be gamerinfo.id, which would then pull all relevant data from gamerinfo, which would pull all relevant data from rosters, which would pull all relevant data from rosterinfo, which would pull all relevant data from gameinfo, which would then pull all relevant data from platforminfo.
Basically it breaks down like this:
gamerinfo contains the gamers basic
information.
rosterinfo contains basic information about the rosters
(ie name and the game the roster is
aimed towards)
rosters contains the actual link from the gamer to the
different rosters (gamers can be on
multiple rosters)
gameinfo contains basic information about the games (ie
name and platform)
platform info contains information about the
different platforms the games are
played on (it is possible for a game
to be played on multiple platforms)
I am pretty new to SQL queries involving JOINs and UNIONs and such, usually I would just break it up into multiple queries but I thought there has to be a better way, so after looking around the net, I couldn't find (or maybe I just couldn't understand what I was looking at) what I was looking for. If anyone can point me in the right direction I would be most grateful.
There is nothing wrong with querying the required data step-by-step. If you use JOINs in your SQL over 5 tables, we sure to have useful indexes on all important columns. Also, this could create a lot of duplicate data:
Imagine this: You need 1 record from gamerinfo, maybe 3 of gameinfo, 4 ouf of rosters and both 3 out of the remaining two tables. This would give you a result of 1*3*4*3*3 = 108 records, which will look like this:
ID Col2 Col3
1 1 1
1 1 2
1 1 3
1 2 1
... ... ...
You can see that you would fetch the ID 108 times, even if you only need it once. So my advice would be to stick with mostly single, simple queries to get the data you need.
There is no need for UNION just multiple JOINs should do the work
SELECT gameinfo.id AS g_id, gameinfo.name AS g_name, platforminfoid.name AS p_name, platforminfoid.abbreviation AS p_abb, rosterinfo.name AS r_name
FROM gameinfo
LEFT JOIN platforminfo ON gameinfo.platforminfoid = platforminfo.id
LEFT JOIN rosters ON rosters.gameinfoid = gameinfo.id
LEFT JOIN rosterinfo ON rosterinfo.id = rosters.rosterinfoid
WHERE gameinfo.id = XXXX
this should pull all info about game based on game id
indexing on all id(s) gameinfoid, platformid, rosterinfoid will help on performance