Employee attendance table in better way? - sql

(source: muchmore.url.ph)
Here's it is how I want to design my SQL database table for employee attendance record.
Is this a correct way to do it?
As we can see it goes on increases date column row from 01 Jan 2014 to 31 Dec 2014 also next years too. so is there any other solution for this?

You could do it in the following way
EmployeeMaster
EmployeeId int primary key
EmployeeCode nvarchar(20)
EmployeeName nvarchar(50)
AttendanceDetails
AttendanceDetailsId int primary key
EmployeeId int foreign key references EmployeeMaster Employee Id
DateofDay datetime
PresentAbsent bit
SalaryDetails
SalaryDetailsId
EmployeeId int foreign key references EmployeeMaster Employee Id
Salary float
While selecting and showing you can play with the records with joins.
you can pivot the records like Transpose in mathematics. There are plenty of ways to achieve it

Databases are designed to cope with large amounts of data. Don't worry about the number of rows in your table.
Make sure you can access all the data with efficient queries, this will be much better than fewer rows
Write some ideas down of how you want to access your data, e.g:
Was EmployeeX in on Week2
Recalculate the number of days in a month
How many days off were sick days/holiday
Then work out what table structures you need to support this with simple queries
For the three above it becomes quite clear that your proposed table structure is going to make your SQL difficult.
Something more like EmployeeID | Date | Hours | Expected Hours | Absence Reason Might be more effective

Yes. Your table is in de-normalized form. This is not a correct way to design database. Try to normalize. Split this table into several tables with proper relationships. Search for normalization, learn how to do it.
For example, You shouldn't keep Leave details and salary details along with attendance. Employee can be related with attendance, leave and salary tables by his ID while Employee details will be a separate Table which contains Employee's personal details.
You can do some thing like this:
EmployeeMaster{EmpID,FirstName,LastName,Address1,Address2,Address3,Address4,ContactNo,JoinnedDate}
SalaryMaster{EmpID, Basic, Variable, Allowance, Bonus, EPF,TAX}
LeaveMaster{ LeaveID,EmpID,StartDate,EndDate,Type,NoOfHalfDays)
Attendance { AttID, DateTimePunchedIn,DateTimePunchedOut}

Related

Add logical constraint while designing tables

I have a table like below:
Student:
StudentId FirstName LastName Grade
Course:
CourseId Name Desc
Offering
OfferNum CourseId ProfessorId
Student_Course_Mapping
OfferNum StudentId
I have a constraint which says that student can enrol only in 2
offering for 1 term and year.
For eg: Lets say student john has enrol in Java and Python for Winter
term(January - April) 2020 than he cannot enrol in other courses.
I don't have any front end or anything else to restrict this. I only have been told to work with the database and apply this constraint.
Right now we are entering data manually in this table using SSMS design view.
So is it possible to restrict someone entering such data?
This type of numeric constraint between two tables is not trivial to implement.
Here are four approaches.
(1) Create a table with one row per student, term, and year. Have two columns, one for each course. It is not possible to have more than two with this approach.
(2) Create a user-defined function that calculates the number of courses for a student in a given term and year. Then create a check constraint using this function.
(3) Create a with one per student, term, and year and a count of the courses for the term. Maintain this count using a trigger and place a check constraint on the value.
(4) Maintain all the logic in the "application". This would entail doing all inserts via a stored procedure and having the stored procedure validate the business logic.
In your case, I would probably opt for (2) as the last intrusive solution. If you already had a table with one row per student/term/year, I would suggest (3). It does involve a trigger (argggh!) but it also maintains useful information for other purposes.

Assign unique ID to duplicates in Access

I had a very big excel spreadsheet that I moved into Access to try to deal with it easier. I'm very much a novice. I'm trying to use SQL via Access.
I need to assign a unique identifier to duplicates. I've seen people use DENSE_RANK in SQL but I can't get it to work in Access.
Here's what I'm trying to do: I have a large amount of patient and sample data (20k rows). My columns are called FULL_NAME, SAMPLE_NUM, and DATE_REC. Some patients have come in more than once and have multiple samples. I want to give each patient a unique ID that I want to call PATIENT_ID.
I can't figure out how to do this, aside from typing it out on each row. I would greatly appreciate help as I really don't know what I'm doing and there is no one at my work who can help.
To illustrate the previous answers' textual explanation, consider the following SQL action queries which can be run in an Access query window one by one or as VBA string queries with DAO's CurrentDb.Execute or DoCmd.RunSQL. The ALTER statements can be done in MSAcecss.exe.
Create a Patients table (make-table query)
SELECT DISTINCT s.FULL_NAME INTO myPatientsTable
FROM mySamplesTable s
WHERE s.FULL_NAME IS NOT NULL;
Add an autonumber field to new Patients table as a Primary Key
ALTER TABLE myPatientsTable ADD COLUMN PATIENT_ID AUTOINCREMENT NOT NULL PRIMARY KEY;
Add a blank Patient_ID column to Samples table
ALTER TABLE mySamplesTable ADD COLUMN PATIENT_ID INTEGER;
Update Patient_ID Column in Samples table using FULL_NAME field
UPDATE mySamplesTable s
INNER JOIN myPatientsTable p
ON s.[FULL_NAME] = p.[FULL_NAME]
SET s.PATIENT_ID = p.PATIENT_ID;
Maintain third-norm principles of relational databases and remove FULL_NAME field from Samples table
ALTER TABLE mySamplesTable DROP COLUMN FULL_NAME;
Then in a separate query, add a foreign key constraint on PATIENT_ID
ALTER TABLE mySamplesTable
ADD CONSTRAINT PatientRelationship
FOREIGN KEY (PATIENT_ID)
REFERENCES myPatientsTable (PATIENT_ID);
Sounds like FULL_NAME is currently the unique identifier. However, names make very poor unique identifiers and name parts should be in separate fields. Are you sure you don't have multiple patients with same name, e.g. John Smith?
You need a PatientInfo table and then the SampleData table. Do a query that pulls DISTINCT patient info (apparently this is only one field - FULL_NAME) and create a table that generates unique ID with autonumber field. Then build a query that joins tables on the two FULL_Name fields and updates a new field in SampleData called PatientID. Delete the FULL_Name field from SampleData.
The command to number rows in your table is [1]
ALTER TABLE MyTable ADD COLUMN ID AUTOINCREMENT;
Anyway as June7 pointed out it might not be a good idea to combine records just based on patient name as there might be duplicates. Better way will be treat each record as unique patient for now and have a way to fix patient ID when patient comes back. I would suggest to go this way:
create two new columns in your samples table
ID with autoincrement as per query above
patientID where you will copy values from ID column - for now they will be same. But in future they will diverge
copy columns patientID and patientName into separate table patients
now you can delete patientName column from samples table
add column imported to patients table to indicate, that there might be some other records that belong to this patient.
when patients come back you open his record, update all other info like address, phone, ... and look for all possible samples record that belong to him. If so, then fix patient id in those records.
Now you can switch imported indicator because this patient data are up to date.
After fixing patientID for samples records. You will end up with patients with no record in samples table. So you can go and delete them.
Unless you already have a natural key you will be corrupting this data when you run the distinct query and build a key from it. From your posting I would guess a natural key would be SAMPLE_NUM. Another problem is that if you roll up by last name you will almost certainly be combining different patients into one.

Database design for customer to skills

I have an issue where we have a customer table includes name, email, address and a skills table which is qts, first aid which is associated by an id. For example
Customer
id = 1
Name = James
Address = some address
Skills
1, qts
2, first aid
I am now trying to pair up the relationship. I first came to a quick solution just by creating a skills table which just has customerId and each skill has a true / false value. Then created a go between customer_skills with an customerId to SkillId. But I would not know how to update the records when values change as there is no unique id.
can anyone help on what would be the best way to do this?
thanks....
The solution you want really depends on your data, and is a question that has been asked thousands of times before. If you google
Entity Attribute Value vs strict relational model you will see countless articles
comparing and contrasting the methods available.
Strict Relational Model
You would add additional BIT or DATETIME fields (Where a NULL datetime represents the customer not having the skill)
to your customer table for each skill. This works well if you have few skills that are unlikely to change much over time.
This allows simple queries to locate customers with skills, especially with various combinations of skills ee.g (Using datetime fields)
SELECT *
FROM Customer
WHERE Skill1 >= '20120101' -- SKILL 1 AQUIRED AFTER 1ST JAN 2012
AND Skill2 IS NOT NULL -- HAS SKILL 2
AND Skill2 IS NULL -- DOES NOT POSSESS SKILL 3
Entity-Attribute-Value Model
This is a slight adaptation of a classic entity-attribute-value model, because the value is boolean represented by the existence of a record.
You would create a table like this:
CREATE TABLE CustomerSkills
( CustomerID INT NOT NULL,
SkillID INT NOT NULL
PRIMARY KEY (CustomerID, SkillID),
FOREIGN KEY (CustomerID) REFERENCES Customer (ID),
FOREIGN KEY (SkillID) REFERENCES Skills (ID)
)
You may want additional columns such as DateAdded, AddedBy etc to track when skills were added and who by etc, but the core principles can be gathered from the above.
With this method it is much easier to add skills, as it doesn't require adding columns, but can make simple queries much more complicated. The above query would have to be written as:
SELECT Customer.*
FROM Customer
INNER JOIN
( SELECT CustomerID
FROM CustomerSkills
WHERE SkillID IN (2, 3) -- SKILL2,SKILL3
OR (SkillID = 1 AND DateAdded >= '20120101')
GROUP BY CustomerID
HAVING COUNT(*) = 2
AND COUNT(CASE WHEN SkillID = 3 THEN 1 END) = 0
) skills
ON Skills.CustomerID = Customer.ID
This is much more complext and resource intensive than with the relational model, but the overall structure is much more flexible.
So to summarise, it really depends on your own particular situation, there are a few factors to consider, but there are plenty of resources out there to help you decide.
If you have a table linking the primary keys from two other tables together in order to form a many-to-many relationship (like in you example) you don't have to update that table. Instead you can just delete and reinsert values into it.
If you are editing a custiomer (customerId 46 for instance) and changing the skills for that customer, you can just delete all skills for the customer and then reinsert the new set of skills when storing the changes.
If your "link table" contains some additional information besides just the two primary key columns, then the situation might be different. But from your description it seems like you just want to link the table together using the primary keys from each table. In that case a delete + reinsert should be fine.
Also in this kind of table, you should make the combination of the two foreign key fields be the primary key of the binding table.

Access Appointment System

I'm trying to produce a Dr-patient appointment system. So far I have four tables:-
Patient:- Doctor:- Appointment:- Availability:-
patientID doctorName time time
name room date doctorName
address patientID
doctorName
All relationships are 1 to manys, with the many side coming out of the appointment table.
Patient:- The table for patient details
Doctor:- The table for doctor details
Appointment:- the table for appointments
Availability:- The table which stores timeslots each doctor is available
However this is all relatively new stuff to me and I'm getting quite thrown. Firstly in the doctors table should I have a field for DoctorID and use that as a primary key instead of the doctors name? Even though there's only likely to ever be a handful of records in that table.
Secondly if I was to change to DoctorID in all tables instead of the doctorName would I still easily able to access the doctorsName if and when required? This part is what confuses me, maybe I'm just over thinking these things.
The reason I ask is for example say I was to produce a report of an appointment which showed the doctorID, I should be able to get the doctors name for the report based on the relationship right? Likewise for the patient based on patient ID.
I'm guessing I also have enough information in the tables to check against and prevent appointment clashes.
Many thanks,
You really should use a doctorsid instead of a doctorsName. Because if you are planing to join these tables together then it is much better to join on ints then on varchars.
And another question if you are still going with the varchar solution what will happened if the doctor change its name (marriage or so). The you need to update the realted tables and the doctor table. If you then are going with the int you just have to change it in one place (the doctor table)
Yes and when you are going to produce you appointment report. You need to get the doctors name by joining the tables.
So your table structure should look something like this:
Patient:- Doctor:- Appointment:- Availability:-
patientID DoctorId AppointmentTime AvailabilityTime
PatientName room AppointmentDate DoctorId
address doctorName patientID
DoctorId

What is the best way to copy data from related tables to another related tables?

What is the best way to copy data from related tables to another related tables with same schema. Table are connected with one-to-many relationship.
Consider following schema
firm
id | name | city.id (FK)
employee
id | lastname | firm.id (FK)
firm2
id | name | city_id (FK)
employee2
id | lastname |firm2.id (FK)
What I want to do is to copy rows from firm with specific city.id to firm2 and and their employees assosiated with firm to table employee2.
I use posgresql 9.0 so I have to call SELECT nextval('seq_name') to get new id for table.
Right now I perform this query simply iterating over all rows in Java backend server, but on huge amount of data (50 000 employee and 2000 of firms) it takes too much time ( 1-3 minutes).
I'm wondering is there another more tricky way to do it, for example select data into temp table? Or probably use store procedure and iterate over rows with cursror to avoid buffering on my backend server?
This is one problem caused by simply using a sequence or identity value as your sole primary key in a table.
If there is a real-life unique index/primary key, then you can join on that. The other option would be to create a mapping table as you fill in the tables with sequences then you can insert into the children tables' FKs by joining to the mapping tables. It doesn't completely remove the need for looping, but at least some of the inserts get moved out into a set-based approach.