Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
Based on my situation, should I combine all symptoms into one row as my method 1 below or method 2 that create more rows. The reason I don't like method 1 is that I have to use - to separate each symptom, and later I need to use php explode('-') to separate them and use LIKE to match them.
Method 2 will create more rows, and I think I will create more table to separate them.
Method 1:
disease symptoms
HIV pain-cough-hair loss
Flu cought-running nose-fever
cacer lose weight-fever-fatigue
Method 2:
disease symptoms
HIV pain
HIV cough
HIV hair loss
... ...
... ...
Out of your two methods, method 2 would be preferred. As #JNevill notes, storing multiple pieces of data in one column becomes a nightmare when searching or filtering data.
My full recommendation would be to use option 3 however. Take a look at the below design:
Table 1: DISEASES
+------+-----------+
| id | name |
+------+-----------+
| 1 | HIV |
|------|-----------|
| 2 | FLU |
|------|-----------|
| 3 | Cancer |
+------+-----------+
Primary Key:
id
Table 2: SYMPTOMS
+------+-----------+
| id | name |
+------+-----------+
| 1 | pain |
|------|-----------|
| 2 | cough |
|------|-----------|
| 3 | hair-loss |
+------+-----------+
Primary Key:
id
Table 3: DISEASES-SYMPTOMS
+-------------+--------------+
| disease_id | symptom_id |
+--------------+--------------+
| 1 | 1 |
|--------------|--------------|
| 1 | 2 |
|--------------|--------------|
| 1 | 3 |
+--------------+--------------+
Primary Key:
(disease_id, symptom_id)
Foreign Keys:
DISEASES.id -> DISEASES_SYMTPOMS.disease_id
SYMTPOMS.id -> DISEASES_SYMTPOMS.symptom_id
Establish your base tables DISEASES and SYMPTOMS. Then establish a 3rd table representing a JOIN of the first two tables. This normalization of the data will simply the structure of your application and prevent duplication of data since each disease can have multiple symptoms and each symptom can belong to multiple disease.
SAMPLE QUERY (MySQL):
SELECT
d.id,
d.name,
s.name
FROM DISEASES as d
INNER JOIN DISEASES_SYMPTOMS AS ds ON d.id = ds.disease_id
INNER JOIN SYMPTOMS AS s ON ds.symptom_id = s.id;
SAMPLE QUERY RESULT:
+------+----------------+----------------+
| id | disease_name | symptom_name |
+------+----------------+----------------+
| 1 | HIV | pain |
|------|----------------|----------------|
| 1 | HIV | cough |
|------|----------------|----------------|
| 1 | HIV | hair-loss |
+------+----------------+----------------+
It depends how normalized you want your database to be. The more normalized approach would be to create a symptoms table that houses all symptoms, a disease table that houses all diseases, and another table with links diseases to symptoms probably by disease_id and symptom_id. And the less normalized approach is like your method 1 where you include all the symptoms as a field in the table separated by some delimiter or put into an array if you are using a database that supports arrays.
Create two master tables for disease & symptoms. And then create a third table say .disease_symptom include the two foreign key column say disease_id & symptom_id and refer to the corresponding master table
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have three tables and I would like to select from the tables without producing duplicates.
The table are as follows:
Customers
id | name | lastName
---------------------------------------
1 | john | doe
2 | helen | keller
Orders
The userID column is a foreign key that references John Doe, so John orders 3 items.
id | userID | order
---------------------------------------
1 | 1 | pizza
2 | 1 | pasta
3 | 1 | lasagna
CustomerRating
The userID column is a foreign key that references John Doe, so John leaves 5 reviews.
id | userID | rating | comment
-------------------------------------------------
1 | 1 | 5/5 | was good
2 | 1 | 5/5 | excellent
3 | 1 | 4/5 | great
4 | 1 | 4/5 | great
5 | 1 | 4/5 | great
How would I select from the 3 tables where I can get a return results that look like this?
id | name | lastName | order | rating
-----------------------------------------------------------------
1 | john | doe | pasta | 5/5
| | | pizza | 5/5
| | | lasagna | 4/5
| | | | 4/5
| | | | 4/5
I've tried joining these tables, but since John has left 5 reviews and only ordered 3 times, the id, name,lastName, and order columns gets filled with duplicate data.
Thanks!
I don't have any experience in MySQL but I assume that it works similar to MSSQL.
So the format in which you are expecting the output is not possible. You can rather get the order and rating column values as comma separated
Here is a similar kind of question that might help you
including example based on link
try something like this
SELECT Customers.id, Customers.name, Customers.lastName,
GROUP_CONCAT(Orders.order) OrderedDishes,
GROUP_CONCAT(CustomerRating.rating) RatingsGiven
FROM
..... rest of your query .....
There are ways to discard duplicates (SELECT DISTINCT, UNION, GROUP BY) but it is not clear whether users update existing rating or create new ones. And what you want to see: the last rating or the average one
On the other note - i would change your entire setup:
order table would contain order_id, customer_idand other order related stuff like order_date
products table that would describe each of your dishes and their info like price, description etc
order_products table with fields order_id and prduct_id
if users rate products then your rating table would need at least product_id, customer_id, rate_value. I'd also add ratingDate That way you can get averages or select the last one by Max(ratingDate)
I think you need to add an orderID field to the CustomerRating table else there is no way to relate an item to its rating.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Database 1 : sandbox
table 1 : coordinates
+----------------------------------------+
|coord_id | section_name | station_number|
+----------------------------------------+
| 1 | A | A7 |
| 2 | B | B20 |
| 3 | C | C3 |
| 4 | D | D14 |
| 5 | E | E9 |
+----------------------------------------+
database 2 : phone
table 2 : workstations
I only have READ privilege
+----------------------------+
| ID | ws | pod |
+----------------------------+
| 1 | COMP123 | A07 |
| 2 | COMP345 | B20 |
| 3 | COMP567 | C03 |
| 4 | COMP891 | D14 |
| 5 | COMP444 | E09 |
+----------------------------+
PROBLEM:
I only have READ privilege on that second table of that database.
I want to join both tables so I can display the "ws" field on screen for my PHP script.
My "station_number" field values are written differently from the "pod" field
(they have a zero in front of the letter if it is a single digit after the letter) does it make a difference?
I've seen examples online on how to join but for some reason I can't get it to work.
Do I need to create an extra field on my main Table to store the field values from "ws" or what? I'm a bit confused.
Thanks in advance!
Yes, it makes a difference if there's a 0 in one and not in the other. You'll have to modify the value of one or the other. Something like SUBSTR(station_number, 0, 1) + LPAD(SUBSTR(station_number, 2), 2, '0').
And to join the tables from different databases, you just have to put the database name in front of the table name. Probably something like sandbox.coordinates.
So your query might look something like this:
SELECT
*
FROM
sandbox.coordinates c
INNER JOIN phone.workstations w
ON (SUBSTR(c.station_number, 0, 1) + LPAD(SUBSTR(c.station_number, 2), 2, '0')) = w.pod
If you can update one of your tables to make the columns match, then your query is as simple as:
SELECT
*
FROM
sandbox.coordinates c
INNER JOIN phone.workstations w
ON c.station_number = w.pod
Hi I have 2 table Offense table and User_jobs table
offense table:
crime_id |crime_type |casenumber|
---------+-----------+----------+
1 | 3 |1 |
2 | 3 |1 |
1 | 3 |2 |
12 | AA |2 |
user_jobs table:
casenumber |disposal_status |
-----------+----------------+
1 | yes |
1 | yes |
2 | no |
2 | no |
what i want is to count the number of rows with the same combination say crime_id=1 and crime_type= 3 but these must have a disposal status of yes in the user_jobs table.
i want to do this in mysql. pliz help
sorry but i am new to mysql. i now want to display the real names of those id not the id themselves.
the tables with these IDs are crime_category and Crime_type Crime_catgory
table:
category |crime_id |
-----------+----------------+
theft | 1 |
murder | 2 |
rape | 3 | 2 |
no |
Crime_type table:
Crime_type |id |
---------------+----------------+
administrative | yes |
criminal | yes |
You can do this with a simple inner join and an aggregate function:
select
o.crime_id,
o.crime_type,
count(*)
from
offence o
join user_jobs uj
on o.casenumber=uj.casenumber
where
uj.disposal_status='Yes'
group by
o.crime_id,
o.crime_type
This will pick up distinct combinations of the first two columns joined as they should tot he jobs table and only where the disposal_status is equal to 'Yes'
Edit: You would probably do really well to have a read of this Q&A that I put together for exactly this sort of situation - where I give you the code for it, but would like to explain this is a lot more detail. The Q&A explains why this type of thing (and many many others) work and how they do so:
How can an SQL query return data from multiple tables
Edit 2:
select
o.crime_id,
o.crime_type,
ct.category,
count(*)
from
offence o
join user_jobs uj
on o.casenumber=uj.casenumber
join crime_type ct
on o.crime_type=ct.crime_id
where
uj.disposal_status='Yes'
group by
o.crime_id,
o.crime_type,
ct.category,
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I have a platform with multiple clients and each has a large set of demographics that I need to store. With this in mind, it seems I could do one of two things in MySQL. Either:
Option #1: Have a large table with everyone's demographics. For example:
Table: clientDemographics
id | clientID | firstName ....
1 | 34 | John ......
2 | 12 | Fred ......
Option #2: Split out each client to having their own table:
Table: client34_demographics
id | firstName ....
1 | John ......
Table: client12_demographics
id | firstName ....
1 | Fred ......
Are there any advantages to splitting the tables out by client (efficiency, security, scalability) or disadvantages? Which of these would be a better method? Thanks!
Your second example is not a good idea (creating a table for each demographic). Instead, I would go with something more "normalized" that contains unique identifiable information in the client table, and then additional meta data (demographics) as a lookup:
Table: Clients
ClientId | FirstName | LastName | Email
-------------------------------------------------
1 | John | Smith | jsmith#email.com
Table: Demographics
DemographicId | Name
-------------------------------------------------
1 | Gender
2 | Nationality
3 | Age
Table: Clients_Demographics
CDId | ClientId | DemographicId | Value
-------------------------------------------------
1 | 1 | 1 | Male
2 | 1 | 2 | American
3 | 1 | 3 | 27
In this way you can easily sort on demographic types, demographic values, clients, etc and all the while saving space in your database, increasing query performance, and keeping your data scalable. By scalable I mean, need to add another Demographic? Just add another row to the Demographics table and then associate a value in the Clients_Demographics table with a Client. If they value is not set (i.e. no row exists) then you know that value can be seen as empty in your forms until they actually set a value.
I have a scenario and i'm confused about how i can go about designing the database schema for it.
In my software (php)
there are companies and applications.
companies need to have licenses to access applications.
now the fields (for form while purchasing licenses) for each application is different.
for ex:
for application1:
fields are:
no of users
no of groups
for application2:
no of users
for application3:
number of hours of usage
Prices are based on these fields.
Now i need to design schema for this so that on one page company can manage licenses for all applications.
How can i make this schema generic?
Please help.
Thanks.
You can go with this type of structure
select * from applicationMaster
| APPID | APPNAME |
------------------------
| 1 | Application1 |
| 2 | Application2 |
ApplicationMaster will go with main Application related details which won't be repeated such Name, date etc.
Query 2:
select * from applicationField
| FIELDID | APPID | FIELDNAME |
---------------------------------
| 1 | 1 | NoOfUsers |
| 2 | 1 | NoOfGroups |
| 3 | 2 | NoHourusage |
ApplicationField can adjust any number of field for a particular appId.
So AppId 1 has 2 fields NoofUsers and NoOfGroups. It is also capable to adjust newer fields for a particular app if you want.
Query 3:
ApplicationValue will have the values for every license aplication so it will have compId which represents which company has applied using fieldId which refers to applicationField table we can get for which app values are stored.
select * from applicationValue
| ID | COMPID | FIELDID | FIELDVALUE |
--------------------------------------
| 1 | 1 | 1 | 50 |
| 2 | 1 | 2 | 150 |
| 3 | 2 | 3 | 350 |
| 4 | 3 | 1 | 450 |
| 5 | 3 | 2 | 50 |
applicationPriceMaster stores the price package for each application. There could be multiple package for a application.
select * from applicationPriceMaster
| APPPACKAGE | APPID | TOTALPRICE |
-----------------------------------
| 1 | 1 | 50 |
| 2 | 1 | 100 |
For each application package its details will posted in this table.
select * from applicationPriceDetail
| APPPACKAGE | FIELDID | QUANT |
--------------------------------
| 1 | 1 | 1 |
| 1 | 2 | 1 |
| 2 | 1 | 10 |
| 2 | 2 | 1 |
NOTE Please check the structure as it is now too complex and check what type of queries you would be running on these table and its performance.
select apm.APPPACKAGE, TOTALPRICE from
applicationPriceMaster apm
inner join
(select APPPACKAGE from applicationPriceDetail
where FIELDID=1 and QUANT=1)a
on apm.APPPACKAGE = a.APPPACKAGE
inner join
(select APPPACKAGE from applicationPriceDetail
where FIELDID=2 and QUANT=1)b
on
a.APPPACKAGE=b.APPPACKAGE
SQL FIDDLE:
| APPPACKAGE | TOTALPRICE |
---------------------------
| 1 | 50 |
For single filter you have to use this query, so you have to increase number of inner query with the number of inner filter.
select apm.APPPACKAGE, TOTALPRICE from
applicationPriceMaster apm
inner join
(select APPPACKAGE from applicationPriceDetail
where FIELDID=1 and QUANT=1)a
on apm.APPPACKAGE = a.APPPACKAGE
NOTE-This query is quite complex and will only work if the values are same as mentioned in the packagedetail table and will work only if the values are 2 filter you have to remove 1 inner join if there is only 1 filter. So I suggest you to reconsider before using this approach.
What you have there, could be easily mapped to Classes in an OO language (like PHP). You have an Abstract License, and then 3 Subclasses (ApplicationByUsersAndGroups, etc). Then, mapping to a Relational database is a very common problem, here is a nice article about it: http://www.ibm.com/developerworks/library/ws-mapping-to-rdb/
It has 3 options, it depends on the way you want to structure your application which one you should use. I recommend reading it, it is not that long.
One way is
Table LICENCES:
LICENSE_ID ==> UNIQUE IDENTIFIER
COMPANY_ID ==> references table COMPANIES
APPLICATION_ID ==> references table APPLICATIONS
LICENCE_TYPE ==> either of "BY_GROUPS_AND_USERS", "BY_USERS", "BY_HOURS"
LICENCE_BODY_ID ==> ID of specific body table
[...]
Table LIC_TYPE_BY_GROUPS_AND_USERS:
LICENCE_BODY_ID ==> body identifier
NO_GROUP
NO_USERS
[...]
Table LIC_TYPE_BY_USERS:
LICENCE_BODY_ID ==> body identifier
NO_USERS
[...]
This way, your intention is clear. Even after long time comming back, you will know in no time how things are organized, which fields are used in which case...
how about a table structured this way:
LicenseId int PK
CompanyId Int PK
AppId Int PK
LicenseType int
NumberOfUsers int
NumberOfGroups int
NumberOfHours int
Price Money
Depending on LicenseType, you will use different column in your business logic,
you might need to add CompanyID and/or AppID, that depends how you going to structure those tables as well as relation ships between company/app/license.
Some questions to think about:
Can one company have different License Types for same App?
Can one company have different Apps?
Dont complicate things, if the number of users is unlimited then set it to 999999 or some other max value.
This keeps the license check logic (which will run every time a user logs in ) simple and the same for all applications.
You will need extra logic in the licenses maintenance application, but this should also be pretty simple:
if the cost_per_user is = 0 then set no_of_users = 99999
Again you end up with the same licensing screen and logic for all your applications.