Inserting data into many-to-many relationship table - sql

I'm trying to build a database with multiple tables for a study/research. This is the first time I'm designing database of this magnitude; the database grows by 100-200 records a day, and so far I have the data since 2010. Out of all the data, Generic Sequence Number, Product Name and the Strength of a drug (prescription) is slightly bothering me. This is what I have done so far:
Generic Seq number is unique to the strength of drug (product name). So, I have a table that contains id, generic seq no, and strength. Another table is for prod_id and product name. Each Generic seq number may have one or more product name, and each product name may have different generic seq number based on the strength. So, I set it up as many-to-many relationship. I created another table for this relationship that contains rx_id, drug_id, and prod_id. Since many patients may be prescribed for the same drug, the drug_id and prod_id may repeat several times in the rx_table.
My first question is, is this design appropriate?
How should I insert the data into rx_table? Should I create new record every time for new data even if the drug_id and prod_id already exist in the rx_table, or should I look for the rx_id where the drug_id and prod_id sequence exist and insert the rx_id into the other main table (not shown) which contains other data.
Or is this question too vague?
Thank you for your help.

I don't know what exactly is your Generic Sequence Number so i'll just use a real life drug example. From your description i think it's pretty similar to your application. Lets say you have Paracetamol as an agent. Then your Generic Sequence Number table would be something like
drug_id | generic_seq_no | strength
--------+--------------------+----------
1 | Paracetamol-100 | 100
2 | Paracetamol-250 | 250
3 | Paracetamol-500 | 500
Your product table would contain the names of the trademarks:
prod_id | prod_name
----------+------------
1 | Tylenol
2 | Captin
3 | Panadol
the rx_table contains the combinations of trademark name, agent and strength:
rx_id | drug_id | prod_id
-------+----------+----------
1 | 1 | 1
2 | 1 | 2
3 | 1 | 3
4 | 2 | 1
5 | 2 | 2
6 | 3 | 2
7 | 3 | 3
So e.g. the first row would be Tylenol, containing 100 mg of Paracetamol. Now you have what can be prescribed by a doctor and that's what you already did so far. So as i said your approach is fine.
Now you need (or have?) another table with all your patients
patient_id | firstname | lastname
-----------+-----------+-----------
1 | John | Doe
2 | Jane | Doe
In the end, you must link your trademark/agent/strength combination to the patients. Since one patient may get different drugs and multiple patients may get the same drug you need another many-to-many-relation, let's call it prescription
prescription_id | patient_id | rx_id
----------------+------------+------
1 | 1 | 1
2 | 1 | 3
3 | 2 | 4
This means John Doe will get Tylenol and Panadol containing 100 mg Paracetamol each. Jane Doe will receive Tylenol with 250 mg Paracetamol. I think the table you will be inserting the most is the prescription table in this model.

Related

Auto generate columns in Microsoft Access table

How can we auto generate column/fields in microsoft access table ?
Scenario......
I have a table with personal details of my employee (EmployDetails)
I wants to put their everyday attendance in an another table.
Rather using separate records for everyday, I want to use a single record for an employ..
Eg : I wants to create a table with fields like below
EmployID, 01Jan2020, 02Jan2020, 03Jan2020,.........25May2020 and so on.......
It means everyday I have to generate a column automatically...
Can anybody help me ?
Generally you would define columns manually (whether that is through a UI or SQL).
With the information given I think the proper solution is to have two tables.
You have your "EmployDetails" which you would put their general info (name, contact information etc), and the key which would be the employee ID (unique, can be autogenerated or manual, just needs to be unique)
You would have a second table with a foreign key to the empployee ID in "EmployDetails" with a column called Date, and another called details (or whatever you are trying to capture in your date column idea).
Then you simply add rows for each day. Then you do a join query between the tables to look up all the "days" for an employee. This is called normalisation and how relational databases (such as Access) are designed to be used.
Employee Table:
EmpID | NAME | CONTACT
----------------------
1 | Jim | 222-2222
2 | Jan | 555-5555
Detail table:
DetailID | EmpID (foreign key) | Date | Hours_worked | Notes
-------------------------------------------------------------
10231 | 1 | 01Jan2020| 5 | Lazy Jim took off early
10233 | 2 | 02Jan2020| 8 | Jan is a hard worker
10240 | 1 | 02Jan2020| 7.5 | Finally he stays a full day
To find what Jim worked you do a join:
SELECT Employee.EmpID, Employee.Name, Details.Date, Details.Hours_worked, Details.Notes
FROM Employee
JOIN Details ON Employee.EmpID=Details.EmpID;
Of course this will give you a normalised result (which is generally what's wanted so you can iterate over it):
EmpID | NAME | Date | Hours_worked | Notes
-----------------------------------------------
1 | Jim | 01Jan2020 | 5 | ......
1 | Jim | 02Jan2020 | 7 | .......
If you want the results denormalised you'll have to look into pivot tables.
See more on creating foreign keys

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

MS access 2007 - checklist options(multiple) to be stored in a column of the database

I have a situation like - the customer form in MS access 2007 have list of documents provided by customers. The list is in the checklist format. Assuming there are 6 documents under the checklist. So if the one or more checklists are selected, all the selected list should be saved in the database column named "Documents_Provided". So in order to achieve this scenario what should I have to do. How should my database field "Documents_provided" should be declared and what do I have to write in VBA code.
As per your Question heading suggests "Multiple to be stored in a Column of the database" is a very bad table design, it breaks one of the rules of Fundamentals of Database Design, Data should be atomic.
The system you should be having is a One to Many, between the Customer and Document table. The Customer table will normally have the basic customer information; one side of the relationship, and the Documents table will have all the documents that pertain to each Customer; many side of the relationship. In Addition you will have another table Document Category that will say what are all the documents that needs/can have for each customer. So sample data in your table will be something like,
tbl_Customers
`````````````
ID | customerName | customerArea
----+-------------------+------------------
1 | Paul | Bournemouth
2 | Eugin | Bristol
3 | Francis | London
tbl_DocumentsCategory
`````````````````````
ID | DocumentName
----+---------------------------
1 | Address Proof
2 | Photo ID
3 | Employer Certificate
tbl_CustomersDocument
`````````````````````
ID | CustomerID | DocumentID
----+---------------+--------------
1 | 1 | 1
2 | 1 | 2
3 | 1 | 3
4 | 2 | 1
5 | 2 | 3
6 | 3 | 2
So when you need to get the list of Documents each Customer has, you simply JOIN the two tables to get the right information. This is the standard and efficient way to organize the data. I hope this helps, and you stick to this.

SQL find duplicates and assign group number

Situation
On a Microsoft SQL Server 2008 I have about 2 million rows. (this should have never happened but we inherited the situation). A sample as follows:
usernum. | phone | email
1 | 123 | user1#local.com
2 | 123 | user2#local.com
3 | 245 | user3#local.com
4 | 678 | user3#local.com
Aim
I would like to create a table that looks like this. The idea is that if 'phone' or 'email' is the same, they are assigned the same group number.
groupnum |usernum. | phone | email
1 | 1 | 123 | user1#local.com
1 | 2 | 123 | user2#local.com
2 | 3 | 245 | user3#local.com
2 | 4 | 678 | user3#local.com
Tried so far
So far I have created a simple python script that conceptually does the following:
- for each usernum in the table
-- assign a group number
-- also assign the group number to all rows where phone or email is the same as this row
-- do not assign the group number if usernum already processed (else we would do things double)
Problem
The python script basically has to check for each row if there are duplicates for phone or email. Although this is perfectly fine for maybe 10,000 records or so, it is too slow for 2 million records. I think this possible to do in t-sql which should be much faster than my python script using pyodbc. The big question thus is, how to do this in sql.
Just noticed you said email or phone is duplicate. For that I would think you would need to decide which has priority in instances where a user could be joined from either field. Or you could potentially just split the update into a few batches to make group numbers based on phone AND email, then email (when not already matched), then phone (when not already matched) as such:
insert into yourGroupsTable (phone, email) -- assuming identity column of groupNum here
select distinct phone, email
from yourUserTable
-- assign group nums with priority on matching phone AND email
update yourUserTable
set groupNum = g.groupNum
from yourUserTable u
join yourGroupsTable g on u.phone = g.phone
and u.email = g.email
It occurs to me now that this would not work as each row would join on the yourGroupsTable due to the distinct select. I came across a scenario that I'm unsure what your expected outcome would be (and too big for a comment) - what happens in this instance:
your test data slightly modified:
groupnum |usernum. | phone | email
1 | 1 | 123 | user1#local.com
1 | 2 | 123 | user2#local.com
? | 3 | 245 | user3#local.com
? | 4 | 678 | user3#local.com
? | 5 | 245 | user7#local.com
? | 6 | 678 | user7#local.com
what would the group numbs be in the above case?
As you do python script is good way ... if you want to move with mysql make it one procedure before inserting record must check its exist or not in table
If Exist
THEN get that row groupnum and assign that groupnum to this new record ...
IF Not
Then give new groupnum
but i have still little confusion
now if record is like
5 | 678 | user1#local.com
if this is the case then ?
I assume that both column [phone and email ] is consider to give groupnum.
if my assumption is correct then go with mysql procedure ...

SQL Server 2008 Modified WHERE Statement

My SQL Server 2008 table is constructed as follows:
160 columns consisting of a Ratio_ID and 160 companies as headers
742 rows consisting of the Ratio_ID's per company.
The typical structure would be:
Ratio_ID | Company 1 | Company 2 | To Company 160
part03x0 | 0.01 | 0.03 |
To Ratio_ID742 |
How would I be able to run a Query to request All Companies Where Ratio_ID part03x0 is zero?
Tried to Google this, but explaining it is very difficult.
Hope it makes sense!
Why are you storing the companies as columns? The companies should be placed in their own table, with a unique ID referring to each company. You can than use this ID with the Ratio_ID in order to perform the query.
160 columns is a massive overkill. Here is a nice tutorial on how to normalize your database.
EDIT:
You do not need to have a table for each company. You only need one table named, for example, tbl_Company and just add the following:
company_id | company_name
1 | CompanyNameOne
2 | CompanyNameTwo
3 | CompanyNameThree
Another table for your Ratios, tbl_Ratio
ratio_id | ratio_name
1 | RatioNameOne
2 | RatioNameTwo
Then combine both using ForeignKeys and Relationships between the two tables into a separate table as below:
tbl_Company_Ratio
company_id | ratio_id | ratio_amount
1 2 5
1 1 2
3 2 10
2 2 5
....