I'm pulling from a table in Oracle SQL developer that has fields: Id number, YEAR, DAY, and MONTH. The YEAR, DAY, MONTH fields are NUMBER data type.
I want to pull data from this table where the Year is between sysdate and 5 years ago. I'm having a problem with these fields being a number field and they are in separate columns. Could someone please help me with this?
It is a bad design storing single components of a date in different columns (I fear you will notice problems quite soon).
Try this one:
WHERE TO_DATE(YEAR||'-'||MONTH||'-'||DAY 'YYYY-MM-DD') BETWEEN ADD_MONTHS(SYSDATE, -5*12) AND SYSDATE
SELECT *
FROM YOUR_TABLE
WHERE TO_NUMBER(YOUR_TABLE."YEAR")>=TO_NUMBER(TO_CHAR(SYSDATE - INTERVAL '5' YEAR, 'YYYY'));
Related
I am trying to create a Attendance result set in SQL Server for using it in a SSRS report. The Employee Attendance table is as below:
EmpId
ADate
In
Out
1
2023-01-01
8:00
15:00
I need to calculate the Total working days for all months in a year and display the number of working days per employee. Report format should be as follows:
Saturday and Sunday being weekend, I can able to get the no of working days monthly.
Another table tbl_Holiday has entries for holidays Fromdate and ToDate. I need to consider that also when calculating working days. Several number of results i got from the internet for calculating this. But when creating a view using this data , it has to calculate workdays for each employee row
SELECT
EmpName, EmpId,
(SELECT COUNT(*) FROM tbl_EmpAttendance
WHERE EmpRecId = A.RecId
GROUP BY MONTH(Adate), YEAR(Adate)) AS WorkedDays,
dbo.fn_GetWorkDays(DATEFROMPARTS(YEAR(ADate), MONTH(ADate), 1), EOMONTH(ADate)) AS workingDays
FROM
tbl_Employee A
LEFT JOIN
tbl_EmpAttendance B ON A.RecId = B.EmpRecId
fn_GetWorkDays - calculates the working days for month.
I need to get number of holidays from tbl_holiday too, I understand that this query is becoming more complex than I thought. There must be simpler way to achieve this, can anyone please help?
I tried to get the result in one single view, for using that as SSRS report dataset
Is there a way to create a table with the following?
Label
“week #1: 1/1/18 - 1/7/18”
“week #2: 1/8/18 - 1/15/18”
And so forth?
Basically, I’m looking for the week number and the date range that week includes.
I think what you want as a starting point, is a "date dimension" or "calendar table". Here's one of many examples for creating them (creating them is not really the issue though, it's how you use them that's more important).
In your example, it looks like you want to pivot the data (create a crosstab). As a rule of thumb, you're generally better off pivoting on the client application, than you are persisting that denormalised anti-pattern in a relational database.
Here's a fictitious example:
DECLARE #start_date as datetime = '20180301';
DECLARE #end_date as datetime = dateadd(dd,datediff(dd,0,GETDATE()),0);--midnight last night
SELECT cal.week_starting --The date of the start of the week eg 15 April 2018.
,dateadd(d,6,cal.week_starting) as week_ending -- The date of the last day of the week eg 21 April 2018. You can cast as varchar, format and concatenate to the previous field to suit yourself.
,my_events.my_category
,count(*) as recs
FROM my.CALENDAR cal
JOIN dbo.big_list_of_events my_events ON cal.census_dttm = my_events.event_date
WHERE my_events.event_date >= #start_date
and my_events.event_date < #end_date
GROUP BY cal.week_starting
,my_events.my_category
ORDER BY cal.week_starting
,my_events.my_category
;
Once you get to this point you're ready to query it with your client application (eg Pivot Tables in Excel) and slice and dice to your heart's content. Again, you probably don't want data stored in your db as a crosstab.
I'm doing a simple query, a select on a table with ID, name and date of birth. I would like to sort of low to high depending on the days that there difference between now and the date of birth of the table. Any ideas? I'm new to SQL and I can not think how.
Table User
SELECT * FROM User ORDER BY
you can use like this
select * from user order by datediff(d,dateofbirth, getdate())
I have 2 Tables with the following fields:
Table_1:
Date, Month, Dayname
2013-01-01, January, Tuesday
This goes from 2013-01-01 to 2013-12-31
Table_2:
Workers_ID, Monday, Monday_Hours, Tuesday, Tuesday_Hours and so forth
1, TRUE, 8, TRUE, 8 ...
2, False, 0, FALSE, 4
What i need is a Table:
Date, Month, Dayname, Hours_to_work, Workers_ID
This Table has Number of workers x Days a year rows and in each row you can see how many hours a specific worker works.
My problem, i have no clue how to accomplish that. It would be greate if someone could help me with it.
Ian P gives good advice as far as revising your schema.
If you're absolutely stuck with the current design, here's a strategy you could use:
SELECT Date, Month, Dayname, Workers_ID,
CASE Dayname
WHEN 'Monday' THEN Monday_Hours
WHEN 'Tuesday' Then Tuesday_Hours
-- etc...
END AS Hours_to_work
FROM Table_1 CROSS JOIN Table_2
Well there are a few things here, but its all part of the learning curve! First, there are functions within MS SQL to provide Month an Dayname, look up DateName and DatePart so if you havnt already, these should be calculated columns on a DateTime or smallDate column. Second, Table_2 is a not an ideal design, in general, tables should be narrow, indexes wide. So Table2 should be of the form WorkersID, Date, Hours and may well have a covering index, or at worst a composite clustered index on Date, EmployeeID. It is then (relatively) easy to produce well perfoming Queries on your data.
If you maintain your structure I would also say a pivot would not help you, I think you want a union against date and employeeId if you maintain your structure. MS SQL also now contains functionality to produce a sequence of values in a range (contiguous range of dates) http://www.sqlperformance.com/2013/01/t-sql-queries/generate-a-set-1
I don't really know how to handle facts that happened over a period of time. I sually deal with facts that happened on a specific date.
In clear, my facts have a start_date and an end_date. So, let's say my start_date is 01/01/2008 and my end_date is 01/01/2011. I need to get the number of those facts that happened in 2009 and those that happened this year. The same fact can have happened on both years. The way to determine a fact is part of 2009 is to check for 12/31/2009.
I was thinking about a StartDate and EndDate dimensions, using date ranges (so from the first date of my StartDate dimension to 12/31/2009 and from 12/31/2009 to the last date in my EndDate dimension). I would cross join those.
I tried it, it works, but it's REALLY slow.
Any thoughts?
I found the solution to what I wanted. David and Chris for the anwsers tho! Here's what I wanted to achieve, but I was lacking MDX syntax :
SELECT [Measures].[NumberX] ON COLUMNS
FROM [MyCube]
WHERE ([START DATE].[REFDATE].FirstMember:[START DATE].[REFDATE].&[2009-12-31T00:00:00],
[END DATE].[REFDATE].&[2010-01-01T00:00:00]:[END DATE].[REFDATE].LastMember)
Pretty simple. I think my question was not clear, that's why I got different answers ;-)
You can always use a date range with the two time dimensions like:
Select [start date].[year].[2009]:[end date].[year].[2010] on 0
from cube
If I'm understanding the question correctly. Two time dimensions should work together fine. I have two in a project I'm doing at work and they work rather fast together. Make sure that you set them up in dimension usage section of the cube so you can differentiate the two dates.
You just need one Date dimension DimDate. Your fact table can have 2 foreign keys to the DimDate, one for startdate and one for enddate.
FactTable
{
FactID int,
StartDate int,
EndDate int
-- Other fields
}
DimDate
{
DimDateID int,
Year int,
Month int,
Day int,
-- Other fields if needed
}
To get all facts that fall on the year 2009, use
SELECT f.FactID FROM FactTable f
INNER JOIN DimDate dStart ON dStart.DimDateID = f.StartDate
INNER JOIN DimDate dEnd ON dEnd.DimDateID = f.EndDate
WHERE dStart.Year <= 2009
AND dEnd.Year >= 2009