Database Table Design guidance - mysql

I am creating a table of pilots with the following fields, would there be any advantage to breaking the table down at each category shown into separate tables and link via the pilots primary key in a one to one relationship?
PILOT PROFILE
username
password
BASIC INFO
first_name
last_name
email
date_of_birth
address_line1
address_line2
town_city
county
postcode
country
tel_no
mobile_no
MEDICAL INFO
med_class
med_issued
med_special
med_verified
med_verified_date
med_verified_by
LICENCE INFO
licence_number
licence_type
licence_tailwheel
licence_retractableGear
licence_vpProp
licence_turboCharged
licence_cabinPressurisation
licence_sep_L
licence_sep_S
licence_mep_L
licence_mep_S
licence_tmg
licence_night
licence_imc
licence_ir
licence_fi
licence_fe
licence_other
licence_verified
licence_verified_date
licence_verified_by
FLIGHT EXPERIENCE
home_airport
hours_total
hours_pic
hours_in12months
hours_verified
hours_verified_date
hours_verified_by
PAYMENT
paid_date

No. Don't break up the row data in this context.
For reasons of performance at scale, sometimes it makes sense to break a table 1:1 into other tables, but given the information provided, this will absolutely not be necessary.
However, on a per-query basis, please do SELECT only the fields needed. Meaning: instead of using SELECT * at whim, use something like SELECT username, password FROM pilot. Side note: don't store your passwords clear text :)

Related

Joining 2 tables together and using the where function based on a separate mysql query

I am building a training platform for work. I have created the requirements for a user to be trained based on a role given to them. If that role is aligned to a document it will sit against the user. I have managed to get most of the way but am struglling on the best way to finish the where statement within mysqli.
tbldocfiles is a list of my files. I am looking at docid (could be multiple files associated to the document)
tbltrainingaccess sets the roles (driver, warehouseman, customer services) and shows which role (by id) is associated to the document in docfiles.
tblusertraining is the list of users and what role they have associated to them. (driver, warehouseman, customer services).
I am listing the documents associated to the user so have thought the following is the best way:
Look at the user and how many roles he/she is allocated
Look at the roles returned in point 1 (where function)
Identify and match the documents that have the same roles as the user (Join function)
create the list, then look at the unique values for docid. (distinct value)
Example User Bri has the driver and warehouseman role.
There are 5 documents in the db, 3 of them are associated to the driver role (docid 1,2,3) and 2 of them are associated to the warehouseman role (docid 2,4) the 5th document is associayted to customerservice.
My query should do this:
List all documents associated to the roles, that are associated to the user Bri
1
2
3
2
4
Now select unique values (using docid) from the above list:
1,2,3,4.
So my answer will be a used as a count function at the end using mysql_fetch_rows
SELECT DISTINCT tbldocfiles.docid FROM tbldocfiles LEFT JOIN tbltrainingaccess ON (tbldocfiles.docid = tbltrainingaccess.docid) where groupid='1' or groupid='9'
The above code works. but i've got myself confused.
The where statement needs to be the result of a query similar to :
select * from tblusertrainingrole where userid='1' (1 will be a variable based on page selection)
the result in this would be 1, 9 which are the groupid results.
Basically any help would be appreciated! I am sure it will be simple but have burnt myself out on this for a while and most answers in here helped with joining but not the where statement (that I could find)
Thank you in advance everyone!
You can do a select statement in the where. Since it is an or statement you can use in for the results. Please replace * with the column name for the value you need. Should look like
where groupid in (select * from tblusertrainingrole where userid = '1')

Front-end SQL Search - Dynamically check similar values?

I have a front-end DB search on my website: https://ygoprodeck.com
Currently it checks card names. A user can type in "magician" and get loads of results.
But if a user mis-spells it and types "magican" then no results show.
I've been tracking user inputs and it seems a lot of users are mis-spelling card names and getting no results.
A common example: There are cards with D/D/D in the name but users often type DDD which means they get no results.
Is there a pure SQL method to modify this behaviour or would it need to be implemented through JS/PHP?
Thanks!
How about saving all the mis-spells in new table like
CREATE TABLE misSpells(
misSpell VARCAHR,
correspondingOne VARCHAR
)
Examples:
magician, magician
magican, magician
DDD, DDD
D/D/D, DDD
and query this table for the corresponding one?

MySQL finding data if any 4 of 5 columns are found in a row

I have an imported table of several thousand customers, the development I am working on runs on the basis of anonymity for purchase checkouts (customers do not need to log in to check out), but if enough of their details match the database record then do a soft match and email the (probably new) email address and eventually associate the anonymous checkout with the account record on file.
This is rolling out this way due to the age of the records, many people have the same postal address or names but not the same email address, likewise some people will have moved house and some people will have changed name (marriage etc).
What I think I am looking for is a MySQL CASE system, however the CASE questions on Stack Overflow I've found don't appear to cover what I'm trying to get from this query.
The query should work something like this:
$input[0] = postcode (zip code)
$input[1] = postal address
$input[2] = phone number
$input[3] = surname
$input[4] = forename
SELECT account_id FROM account WHERE <4 or more of the variables listed match the same row>
The only way I KNOW I can do this is with a massive bunch of OR statements but that's excessive and I'm sure there's a cleaner more concise method.
I also apologise in advance if this is relatively easy but I don't [think I] know the keyword to research constructing this. As I say, CASE is my best guess.
I'm having trouble working out how to manipulate CASE to fit what I'm trying to do. I do not need to return the values only the account_id from the valid row (only) that matches 4 or 5 of the given inputs.
I imagine that I could construct a layout that does this:
SELECT account_id CASE <if postcode_column=postcode_var> X=X+1
CASE <if surname_column=surname_var> X=X+1
...
...
WHERE X > 3
Is CASE the right idea?
If not, What is the process I need to use to achieve the desired results?
What is [another] MySQL keyword / syntax I need to research, if not CASE.
Here is your pseudo query:
SELECT account_id
FROM account
WHERE (postcode = 'pc')+
(postal_address = 'pa')+
(phone_number = '12345678901')+
(surname = 'sn')+
(forename= 'fn') > 3

Database schema practical approach

I want to model 2 entities in database: CafeBrand and Cafe. I have pretty much the same properties in both entities:
CafeBrand{
foodDescription,
website,
email,
phone
}
cafe{
foodDescription,
website,
email,
phone
}
So let's say in case of McDonalds all 'cafes' would have the same foodDescription: 'Junk food'. But some other brands might have separate food description for separate cafes('sandwiches', 'drinks only', ...).
Same with website/email/phone properties: cafe might have its own website/email/phone but also it could be using the same website/email/phone for all of them. Quite often the same CafeBrand has one website but different email/phone for its different cafes.
My question is: is it wise to store these properties as it is and then use if/else (in SQL or code) to get a proper description,website,email,phone (if cafe.website == null then use cafebrand.website) or is it better to use relationships to separate tables 'FoodDescription', 'Website' The data won't be written to the database very often and most of the time only select statements will be used.
And if Company has a single cafe. How should this foodDescription/Website be split into CafeBrand/Cafe tables.
As Bill Gregg has mentioned you should probably put all similar data in one table. So you'll receive following structure:
cafe {
foodDescription,
website,
email,
phone,
brand
}
Because of foodDescription, website and so on columns will contains pretty unique values I assume, you won't gain any profit with separation the data into different tables.

Database Normalization

I've been given the task of normalizing this set of data:
COURSE=(CourseID, CourseName, CourseDuration, CourseFee{
DelegateID, DelegateName, DelegateAddress, EventID, EventName, VenueID, VenueName, VenuePrice, BookingID, BookingType, BookingDate
})
The scenario is an IT company that runs short training courses at various hotels around the country, each event being hosted by one or more presenters (hence the BookingType - either Delegate or Presenter, if Presenter then no booking charge). An event is just an instance of a course running at a particular venue. VenuePrice refers to the cost for optional bed and breakfast at the hotel venue for the intervening nights
Here is what I have come up with for 3NF:
COURSE=(CourseID, CourseName, CourseDuration, CourseFee)
DELEGATE=(DelegateID, DelegateName, DelegateAddress)
EVENT=(EventID, VenueID*, CourseID*, EventName, EventDate)
BOOKING=(BookingID, DelegateID*, EventID*, BookingDate, BookingType)
VENUE=(VenueID, VenueName, VenuePrice)
I'd like to know if this is at all accurate, and if not, perhaps a guiding hand in the right direction?
Thanks
On what basis do you think that is in 3NF ?
Let's take a really simple example, Course. Where exactly if he Functional Dependency, on what key ? How can CourseName be dependent on CourseId, when CourseDuration and CourseFee are dependent on CourseName ?
Same with the rest of the tables; Event being a little more complex, has a few more errors.
You cannot normalise, or achieve 3NF, when your starting point is to stick an ID on everything that moves.
No. First normalise the data. Achieve 3NF. I can understand a CourseCode or ShortName as something the user may use to identify course, but no Id.
After that, if and only if you need to, add an Id column and the additional index.