Relational Database design to store weekly attendance - sql

I need to design a table to store weekly attendance
Format of the form is :
Todays' Date,
Note(if absent for each day)
Monday Y/N
Tuesday Y/N
Wed Y/N
Thurs Y/N
Fri Y/N
How do I design the table to store such information which is recorded on a weekly bases?
Should it be 1 table having columns as
Date , Monday(bit) , MondayNote(varchar) , Tue , TueNote etc upto Fri ?
What is the best approach?
TIA

Instead of storing bits for each day of the week, why not just store the actual date with the flag and note? Something like this:
CREATE TABLE Attendance(AttendanceID int primary key not null identity(1,1), StudentId int not null /* foreign key? */, AttendanceDate date not null, PresenceFlag tinyint not null default(1), Note varchar(max) null);
So instead of using a single date and five flags for days, which would complicate your logic for getting the actual date, store the actual date for each day of the week. This will simplify a lot of query logic.
Note that I am using a tinyint instead of bit. This is to allow you to perform arithmetic operations. SUM(PresenceFlag) will give you total a attendance for a period. You can't do this with bit data type. You can use a CONSTRAINT to ensure only 1 and 0 are allowed.
You can easily get a day of the week from a date using DATENAME(Weekday, AttendanceDate).

Related

How to store day+time slots in sql database

Let's say I have application where owners of shops can add their shops. For each shop I have to store an information when the shop is open. For example
Monday 8:00 - 20:00
Tuesday 9:30 - 22:00
Sunday 11:00 - 18:00
I have a table with shops (id, name, address, e-mail, etc). What is a correct way to store information about these day+time slots when each shop is open in sql database?
There is no one correct way, there are several methods with various advantages and disadvantages.
If you're going to use the data to see if a shop is currently open, I think the most easily used is to define a second table with one day's worth of hours for one store per row
CREATE TABLE StoreHours(
HourID int IDENTITY(1,1) NOT NULL,
StoreID int NOT NULL,
DayOfHours int NOT NULL,
--Could be char(2) if you wanted to store day as Su, M, Tu, ...
--but storing as an integer is useful with other queries
Opens time(0) NOT NULL,
Closes time(0) NOT NULL,
--And maybe LastUpdated datetime(0) if you cared
CONSTRAINT [PK_StoreHours] PRIMARY KEY CLUSTERED ( HourID ASC )
)
Queries can use the date functions (like DatePart) to determine the day of week, which can then be used, along with StoreID, to look up the day's hours.
For example, to find open gas stations, a query might look like this (obviously more useful if you also have geolocation data ...)
SELECT *
FROM Store as S INNER JOIN StoreHours as H on S.StoreID = H.StoreID
WHERE S.TypeOfStore = 'Gas Station'
AND H.DayOfHours = DATEPART(weekday, GETDATE())
AND CONVERT(TIME(0), GETDATE()) < H.Closes
AND CONVERT(TIME(0), GETDATE()) > H.Opens
On the other hand, if you're just displaying them (like on a web site) without making any comparisons, then storing them as a text string would save you work. You could still do the secondary table and one row per day, or you could use one row per store with each day's hours in a dedicated column. That's really hard to use in queries, but very easy to just display.

DayofWeek, Year & Shiftname

I apologize if my questions seems irrelevant or silly. My expertise on SQL is low.
My questions is that I'm trying to create five columns namely ID, shiftName, DayofWeek, date & year in the database.dbo.tablename. However, I'm not sure and couldn't find the right source to correctly write queries for this.
The logic is a day will have 6 shifts, so the DayofWeek, date and year should correspond to the shift column.
Any help would be appreciated.
This is the most simple table I could think of, that would work in MySQL, SQL Server, PostgreSQL, or DB2:
create table tablename (
id int primary key not null,
shift_name varchar(40) not null,
day_of_week int not null,
"date" date not null
);
I excluded the column year since the column date already includes the day, month, and year.

SSAS get active record count between two dates

Can you please let me know the best approach for designing Data ware house and dimension modelling (SSAS cube) based on below requirement.
Requirement here is, I have to get the student count which are active as of that month, if the user selects year (2015) from drop down which is displayed in the image. Catch here there is no option to select enrollstartdate and enrollenddate as two different dates (no role play dimension) , only one filter i.e Year.
Requirement to get the active student count as of that month
There are a couple of possible approaches that come to mind. The first is a periodic snapshot fact table and another is a timespan accumulating snapshot fact table.
In my opinion, the first is easier to implement, so I've provided some detail below that I hope you will find useful.
CREATE TABLE FactEnrollmentSnapshot
(
DateKey INT NOT NULL -- Reference to Date dimension table
, StudentKey INT NOT NULL -- Reference to Student dimension table
);
CREATE TABLE DimStudent
(
StudentKey INT NOT NULL
StudentId ?
...Other Student Attributes...
);
CREATE TABLE DimDate
(
DateKey INT NOT NULL
, FullDate DATETIME NOT NULL
, Year SMALLINT
);
Assuming your date dimension is at the day grain, you could either store daily snapshots, or just store snapshots on the 15th of each month.
Depending on whether you need to get a count of unique students during 2015 or the most recent count of students in 2015 you could use the DISTINCT COUNT aggregation or the LastChild aggregation in SSAS. If you use LastChild, make sure your Date dimension is marked as a Time type.
Note that a snapshot style fact table results in semi-additive facts.
You could get the raw data to populate the fact table from your example source data by using a CROSS JOIN between you source data and the Date dimension
SELECT
StudentTable.StudentID
, DimDate.FullDate
FROM
StudentTable
INNER JOIN DimDate ON (DimDate.FullDate BETWEEN StudentTable.EnrollDate AND ISNULL(StudentTable.DisenrollDate,'9999-12-31'));
I didn't include the lookups for surrogate keys for simplicity
You can then get the answer for your business users be filtering on the Year attribute in the Date dimension.
I hope this is useful in getting you started with a possible approach.
Regards,
Jesse Dyson

Storing datetime or season or quarter in a relational database

I must save an event in a relational database.
This event has a time when it starts.
This will be precisely one of:
a datetime, for example: 05.05.2015 06:00:00
a quarter, for example: 4th quarter of the year 2015
a season, for example: Winter
What would be a good way to store this in a database, so i can distinguish the three types.
Should i create a col for datetype and three other cols for datetime, quarter, season? And what would you use for season and quarter.
Yes, your suggestion makes perfect sense. Create a column for datetype and three other cols for datetime, quarter, season. There are plenty of different ways to do this, here's one approach;
DateType char(1) not null, D = datetime, Q = quarter, S = season
DateTime datetime null
Quarter int null, valid values 1 to 4
Season char(2), valid values Wi, Sp, Su, Au
I would use column constraints to enforce the valid values per column, then a table constraint to enforce the rule that if DateType = D then DateTime must not be null and Quarter and Season must be null etc.
You could skip the Quarter and Season columns and use the DateTime column to store a value to represent quarters 1 to 4 or the seasons but this sort of approach almost always leads to mistakes later on. These values are sometimes called 'magic values' because they aren't what they seem, for example, does 2015-01-01 mean 1st Jan 2015 or 'Quarter 1'? When someone queries your table and forgets to look at the DateType column how will they know? I like to see schemas and data that describe themselves. With my suggestion above (or any similar approach) it would be hard to misinterpret the data in the table.
Saving a few bytes of storage or a few millionths of a second in processing are very rarely worth it - you should design something that will always work all of the time, not something that will work a little quicker, most of the time.

SQL Table for Timesheet creation

I'm creating a timesheet using Infopath. The data will be stored in the database, so for that I have to create a table. This timesheet will be used for the whole year.
I need help in creating a SQL table. The table structure I want for this timesheet is:
Project_Category Mon Tue Wed Thu Fri Sat Sun Total
Project 1
Project 2
Project 3
Project 4
Project 5
Other
Total
The days should be with dates (Like, Monday 01/01/2013) or please suggest me if you have a better way to do this.
I would not store this data in a single table. Consider creating this using multiple tables instead of the single table.
For example, you could have a Projects table with ProjectId and ProjectName. Then you could easily link your ProjectId field to a ProjectSummary table which stores ProjectId, DateField and Total. I have no clue what your Total row is suppose to be, but if it's a calculation of a date range, use SQL to calculate those values and do not store that in the table.
Good luck -- there are lots of resources online to get started with SQL -- do a little searching.
As sgeddes has suggested, multiple tables will probably be a much better way to approach this.
Personally I would avoid having more than 1 day per row and also to make it flexible allow more than one entry per day.
The structure I would create is as follows:
Entry_ID INT IDENTITY(1,1) PRIMARY KEY
Timesheet_ID INT,
Project_ID INT,
DateTimeFrom DATETIME,
DateTimeTo DATETIME
This then allows date based calculations to be much simpler.
eg. Number of hours on project X between 20th June and 25th June would be a query like:
SELECT SUM(DATEDIFF(MINUTES,DateTimeFrom,DateTimeTo)/60) AS [HOURS]
FROM MyTable
WHERE DateTimeFrom >= '2012-06-25' AND DateTimeTo <= '2012-06-29'