Database Design question best way to solve this issue [closed] - sql

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 3 years ago.
Improve this question
I'm kind of new in database design and I'm trying to find the best way to solve an issue I'm facing.
Let's think about the following example:
Imagine I want to store information about patients and these patients can have 0+ diseases.
What's the best way of storing arranging the tables to display the diseases that each patient can have? I get confused as to what happens when a patient would have 3 diseases; how is this stored in a relational database? e.g. without having repeated rows on the diseases table for example (static number of diseases)..
I'm not sure if I'm making myself totally clear here!
But let's say I don't think it's efficient to have:
Patient table -
Patient_id , disease_id
1, (3,4,5,6)
Any help is appreciated!

As mentioned in the comments, you would use an associative entity for that.
Let say you have the following diseases:
| Disease_id | Disease_name |
-----------------------------
| 1 | Cancer |
-----------------------------
| 2 | Leucemia |
-----------------------------
Your patients may look like this
| Patient_id | Patient_name |
-----------------------------
| 1 | Peter Jones |
-----------------------------
| 2 | Mark Jacobs |
-----------------------------
You now create a table like so (lets call it ill_patients)
| Patient_id | Disease_id |
---------------------------
| 1 | 1 |
---------------------------
| 1 | 2 |
---------------------------
This would mean that poor Peter Jones has cancer as well as leucemia. You can now query your patient table like so:
SELECT patients.patient_name, diseases.disease_name
FROM (diseases INNER JOIN ill_patients ON diseases.disease_id = ill_patients.disease_id) INNER JOIN patients ON ill_patients.patient_id = patients.patient_id;
This gives you all the patients with their respective diseaes.

Patients:
patient_id, name, phone
Disease:
disease_id, name, description
Patient_Disease:
patient_id, disease_id
Example:
patient_id, name , phone
1 , 'jhon', '555-1234'
disease_id, name , description
1 , 'Cancer' , 'Cancer is the uncontrolled development of cells.'
2 , 'Diabetes', 'Diabetes is a disease that occurs when your blood glucose is too high.'
patient_id, disease_id
1 , 1
1 , 2
Then you can do
SELECT p.name, d.name, d.description
FROM patients p
JOIN patient_disease pd
ON p.patient_id = pd.patient_id
JOIN diseases d
ON pd.disease_id = d.disease_id

Related

sql query get Data on pre conditions [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
i need fruit list which price greater than in tableA for each fruit.
ID | fruit | Price
----------------------------
1 | apple | 10
2 | banana| 7
3 | grapes| 6
then i have daily table like below
ID | fruit | Price
----------------------------
1 | apple | 9
2 | banana| 5
3 | grapes| 9
4 | mango | 15
in this condition i get only grapes
I think you can just join the daily and tableA tables on the fruit's ID, and then compare prices.
SELECT t1.*
FROM daily t1
INNER JOIN tableA t2
ON t1.ID = t2.ID
WHERE t1.price > t2.price
Note that we join on the ID rather than the fruit name, since in theory names may not be completely unique across a very large table of fruits.
just join by ID and add your additional condition (price in tableA is greater than price in dailyTable).
you don't need to join by column fruit - but if so, it won't change your resultset.
SELECT TableA.*, dailyTable.Price
FROM TableA
INNER JOIN dailyTable
ON TableA.ID = dailyTable.ID
AND TableA.Price > dailyTable.Price
the column fruit is redundant data. so you shouldn't store it in the daily table.

How to make multiple instances of foreign key work in one row

Hello people and fellow SQL programmers.
I have been trying to work out a reality model that is situated in Industry.
The client, that the database is ordered by states that:
There are multiple different job locations/offices where his employees work. Each workplace/office has a set number of people that can work here - minimum and maximum. For each workplace there is a group of people that consists of at least 2 people and max at 4 people. There can be only one group stationed in one work place at a time. There are also a few specifications for the group such as - there are no leaders among them - everybody is equal. A certain worker can only be assigned to only one group at a time. And there is to be an evidence in history who and where worked and for how long.
I have been trying to work the table design with its attributes for quite some time but it seems to me that everything i have done so far has some serious holes and is quite messy. I would very much appreciate any feedback and advice from you guys. Thanks in advance.
If I understand correctly you have two entities: employee and office. These will require two tables:
employee: id, name, whatever_else
office: id, desc, min_employees, max_employees, whatever_else
Theoretically the relationship between these two entities is one-to-many, because you say each employee can only be assigned to a single office at a time, so you could add a office_id foreign key to the employee table.
Having to keep track of the history however means that each employee may have multiple associations with the offices, thus making the relationship many-to-many. You will then need another table to model it:
employeeOffice: employee_id, office_id, start_date, end_date
With this model the queries I imagine you'll need to perform would be quite easy; as an example, finding how many employees are currently assigned to each office would be
select t1.id, t1.desc, count(distinct t2.employee_id)
from office t1
join employeeOffice t2
on t1.id = t2.office_id
where t2.end_date is null
group by t1.id, t1.desc
Edit
Take this sample data as an example
employee
id | name
1 | name1
2 | name2
3 | name3
4 | name4
5 | name5
6 | name6
7 | name7
office
id | desc
1 | office1
2 | office2
employeeOffice
employee_id | office_id | start_date | end_date
1 | 2 | '01-01-2107' | '31-01-29107'
1 | 1 | '01-02-2107' |
2 | 1 | '01-01-2107' |
3 | 1 | '01-01-2107' |
4 | 1 | '01-01-2107' |
5 | 2 | '01-01-2107' | '01-03-2107'
6 | 2 | '01-01-2107' |
7 | 2 | '01-01-2107' |
This would mean that employee 1 spent one month in office 2 and then was assigned to office 1. Employee 5 after two months resigned (or was fired), because there's no record for him with empty end_date.
The example query above would give you
id | desc | count
1 | office1 | 4
2 | office2 | 2

SQL query to select people interviewed more than once in a year

first of all this query will be done in access, I'm trying to find details of people who have been interviewed more than once in a specific year.
It needs to be multi tabled, to both sort out people who have been interviewed more than once in 2013, and the details of those people.
Example
Tables are as follows:
Interview
| ID | InterviewDate |
| 123| 13-12-04 |
| 789| 14-01-10|
| 123| 13-12-21 |
Person
| ID | NAME | NUMBER | LOCATION |
| 123| John| 128231 | USA
| 789| Max | 123556 | Europe
So the list is a bit larger, but ideally I want to be able to make a query that will count whose had an interview more than once in 2013 and their details from another table.
I have this query which apparently works but I'm sure there's a better way to show it as this may have some flaws.
SELECT P.ID, Name, Number, Location, COUNT(year(InterviewDate) AS InterviewNo, Year(InterviewDate) AS Year
FROM Person AS P INNERJOIN Interview as I ON P.ID = I.ID
GROUP BY P.ID, Name, Number, Location, Year(InteviewDate)
HAVING COUNT(Year(InterviewDate)) > 1 AND Year(InterviewDate)='2013'
I feel like the year(InterviewDate) is all wrong, would I be able to get the same result without using that exact phrase? Maybe using a sub-query.
Thank you.
My access syntax is probably a little off, but I think you are asking fro something like:
SELECT P.ID
,Name
,Number
,Location
,InterviewNo
FROM Person P
INNER JOIN
(SELECT ID
,COUNT(1) AS InterviewNo
FROM Interview
WHERE Year(InterviewDate) = 2013
GROUP BY ID
HAVING COUNT(1)> 1) I ON P.ID=I.ID

How do I design a bus route database? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I want to create a bus route DB in such a way that it gives the result as follows :
Input :
Source = station-X , Destination = station-Y
Output : Various bus name/nos. which go through Station-X and Station-Y
So far i have :
Bus(bus_no), Bus_Route()
Bus(bus_name/no.)
id | bus_no
1 | 33
2 | 33A
Bus_Route(route_id,bus_no)
id | route_id | bus_no
1 | route-A | 33
2 | route-B | 33A
How do i proceed to store the station names of the respective routes.
I am no database expert, so any help would be valuable .
Thanks in advance.
You'd be best off creating an extra table holding the STATION - ROUTE relationship. You'd define a many-to-many relationship here, meaning that a station can have many routes, and a route can have many stations.
busses (only necessary if multiple physical busses exist with same *bus_no*)
id | bus_no
---------------
1 | 33
2 | 33A
3 | 33A
bus_routes (both *route_id* and *bus_no* have to be unique values)
route_id | bus_no
---------------------
route-A | 33
route-B | 33A
stations_routes (many-to-many, route_order tells us the order within the route)
route_id | station_id | route_order
------------------------------------
route-A | Egham | 1
route-A | Haymarket | 2
route-A | Egham Plaza | 3
route-B | Egham | 1
route-B | Langley | 2
I think that you need the following tables:
BUSROUTE: route_id, routenumber
BUSSTOPS: stop_id, stopname
BUSROUTESTOPS: route_id, stop_id, displayorder
Using the London Underground as an example, the busroute table would hold values like 'Jubilee', 'Central', 'District', 'Bakerloo', etc.
The busstops table would hold the station names, eg Stanmore, Canons Park, Queensbury, Kingsbury, Wembley Park, etc. This table is necessary as a station can service more than one route.
The busroutestops hold the route number, the station name and the order in which the station appears for this route. The primary key would be an amalgamation of route_id and stop_id.
Once you've got past this, you'll probably need a timetable table, which in its simplest form would contain three fields: an id, a route_id and the departure time. It is left 'as an exercise for the reader' how to represent the return journey!
The London Underground was probably not a good example as some lines - especially the Northern and District lines - have multiple routes. These would best be treated as separate routes.

SQL duration between dates for different persons

hopefully someone can help me with the following task:
I hVE got 2 tables Treatment and 'Person'. Treatment contains the dates when treatments for the different persons were started, Person contains personal information, e.g. lastname.
Now I have to find all persons where the duration between the first and last treatment is over 20 years.
The Tables look something like this:
Person
| PK_Person | First name | Name |
_________________________________
| 1 | A_Test | Karl |
| 2 | B_Test | Marie |
| 3 | C_Test | Steve |
| 4 | D_Test | Jack |
Treatment
| PK_Treatment | Description | Starting time | PK_Person |
_________________________________________________________
| 1 | A | 01.01.1989 | 1
| 2 | B | 02.11.2001 | 1
| 3 | A | 05.01.2004 | 1
| 4 | C | 01.09.2013 | 1
| 5 | B | 01.01.1999 | 2
So in this example, the output should be person Karl, A_Test.
Hopefully its understandable what the problem is and someone can help me.
Edit: There seems to be a problem with the formatting, the tables are not displayed correctly, I hope its readable.
SELECT *
FROM person p
INNER JOIN Treatment t on t.PK_Person = p.PK_Person
WHERE DATEDIFF(year,[TREATMENT_DATE_1], [TREATMENT_DATE_2]) > 20
This should do it, it is however untested so will need tweaking to your schema
Your data looks a bit suspicious, because the first name doesn't look like a first name.
But, what you want to do is aggregate the Treatment table for each person and get the minimum and maximum starting times. When the difference is greater than 20 years, then keep the person, and join back to the person table to get the names.
select p.FirstName, p.LastName
from Person p join
(select pk_person, MIN(StartingTime) as minst, MAX(StartingTime) as maxst
from Treatment t
group by pk_person
having MAX(StartingTime) - MIN(StartingTime) > 20*365.25
) t
on p.pk_person = t.pk_person;
Note that date arithmetic does vary between databases. In most databases, taking the difference of two dates counts the number of days between them, so this is a pretty general approach (although not guaranteed to work on all databases).
I've taken a slightly different approach and worked with SQL Fiddle to verify that the below statements work.
As mentioned previously, the data does seem a bit suspicious; nonetheless per your requirements, you would be able to do the following:
select P.PK_Person, p.FirstName, p.Name
from person P
inner join treatment T on T.pk_person = P.pk_person
where DATEDIFF((select x.startingtime from treatment x where x.pk_person = p.pk_person order by startingtime desc limit 1), T.StartingTime) > 7305
First, we need to inner join treatements which will ignore any persons who are not in the treatment table. The where portion now just needs to select based on your criteria (in this case a difference of dates). Doing a subquery will generate the last date a person has been treated, compare that to each of your records, and filter by number of days (7305 = 20 years * 365.25).
Here is the working SQL Fiddle sample.