Here is my stored procedure to get a list of employees and their hours worked between StartDate and EndDate.
ALTER procedure [dbo].[usp_get_employeehourlyreport]
#startdate datetime,
#enddate datetime
as
begin
select *
from (
select
(select FullName from Registration
where Registration.UserId = UserTime.UserId) Fullname,
ISNULL(SUM(HoursWorked), 0) HoursWorked
from UserTime
where CheckIn between #startdate and #enddate
group by UserId, CheckIn) tbl
end
The result I am getting is :
Fullname HoursWorked
Antonio Jake 0
Antonio Jake 0.016666
So basically it is displaying one row extra with hours 0. I Do not have any duplicate FullName in my database.
Table structures are:
USERTIME:
UserTimeId int Unchecked
UserId int Checked
CheckIn datetime Checked
LoginStatus nvarchar(50) Checked
Day varchar(50) Checked
HoursWorked float Checked
Date nvarchar(50) Checked
REGISTRATION:
UserId int Unchecked
FullName varchar(50) Checked
Try something like this....
ALTER procedure [dbo].[usp_get_employeehourlyreport]
#startdate datetime,
#enddate datetime
AS
BEGIN
SET NOCOUNT ON;
SELECT R.FullName, ISNULL(SUM(UT.HoursWorked),0) AS Total_Hours
FROM Registration R LEFT JOIN USERTIME UT
ON R.UserId = UT.UserId Fullname ,ISNULL(SUM(HoursWorked),0) HoursWorked from UserTime
AND UT.CheckIn >= #startdate
AND UT.CheckIn <= #enddate
GROUP BY R.FullName
END
Related
I have 3 tables with columns shown below,
Holidays : HolidayId, HolidayName, HolidayDate, Comment
Entitlements:
EntitlementId, EmployeeId, LeaveTypeId, LeavePeriodId, FromDate
, UptoDate, Entitlementdays
Weekend: WeekeindId, Weekends
TODO:
create a store procedure for insertion
Before insertion it should check and count the dates in holiday and weekend table
if it is between the date which is in the startdate and enddate of entitlement table should be subtract.
in sql
Try this one as you already have weekend table and holiday table
CREATE PROCEDURE
usp_LeaveDays (#employeeid int)
as
BEGIN
DECLARE #fromdate DATE
SET #fromdate =
SELECT convert( varchar(10),fromdate,120) fromdate
FROM Entitlement
WHERE employeeid = #employeeid
DECLARE #enddate DATE
SET #enddate =
SELECT convert ( varchar(10),enddate,120) enddate
FROM entitlement
WHERE employeeid = #employeeid
DECLARE #weekendcount INT
SET #weekendcount =
SELECT Count(*)
FROM Weekend
WHERE weekends BETWEEN #fromdate AND #enddate;
DECLARE #holidayCount INT
SET #holidaycount =
SELECT Count(*)
FROM holidays
WHERE holidaydate BETWEEN #fromdate AND #enddate
DECLARE #Totaldays INT
SET #Totaldays =
SELECT DATEDIFF(day, #fromdate, #enddate)
DECLARE #Actualdays INT
SET #Actualdays = #Totaldays - (#weekendcount + isnull(#holidayCount, 0))
DECLARE #recordCount INT
SELECT #recordCount = #Actualdays
IF (#recordCount > 0)
begin
insert into -- Enter your script here
END
I have a table "Values" The data looks like this:
ID Label Value
1 StartDate 1/1/17
2 EndDate 1/15/17
3 Dept 6
What I'd like to do is load the values of the "Label" column to the corresponding Parameters in my Query:
Declare
#startdate Datetime,
#enddate Datetime,
#DepartmentID int
Select *
From Customers
Where created between #startdate and #enddate and #DepartmentID
How can I assign #Startdate to the 'Startdate' 'value' in the value table? Additionally, Since i'm using different datatypes in my query, than what they are stored in the Values table (Values are 'nvarchar' in values table) Will I run into potential problems?
Declare
#startdate Datetime,
#enddate Datetime,
#DepartmentID int
set #startdate = (Select convert(datetime,[Value]) from dbo.Values where Label='StartDate')
set #enddate = (Select convert(datetime,[Value]) from dbo.Values where Label='EndDate')
set #DepartmentID =(Select convert(int,[Value]) from dbo.Values where Label='Dept')
Select *
From Customers
Where created between #startdate and #enddate and DepartmentId = #DepartmentID
You could try to do something like this:
SELECT
*
FROM
CUSTOMERS
WHERE
CREATED BETWEEN
(SELECT TOP 1 [Value] FROM Values WHERE Label = 'StartDate') --perform casts here if necessary
AND
(SELECT TOP 1 [Value] FROM Values WHERE Label = 'EndDate') --perform casts here if necessary
I am trying show attendance record for employees in particular Branch, let Say "Pune Branch".
While Showing Weekly Records, It only shows the record of dates for which there is an entry in database table. I also want to show record for those Date on which there is no any employee present.
Suppose In Log_TB there are 2 employee record present for 28 Apr 2015 out of 2 Employees, Then It Shows
And If No records for that Date then it Returns nothing.
I want result Like
Here is my Query
Declare
#Date date = GETDATE(),
#date1 date,
#Total int
set #date1 = (CONVERT(date,DATEADD(DD,-6,#Date),108));
select #Total = Count(User_TB.User_Id)
from User_TB join Branch_TB
on User_TB.User_Branch = Branch_TB.Branch_Name
where User_TB.User_Branch = 'Pune';
select convert(varchar,Log_TB.Date,106) AS Date,
CONVERT(CHAR(3),DATENAME(weekday,Log_TB.Date)) AS Day,
#Total AS Total,COUNT(Log_TB.User_Id) Present,
(#Total-COUNT(Log_TB.User_Id)) AS Absent
From Log_TB join User_TB on Log_TB.User_Id = User_TB.User_Id
where Log_TB.Date <= (CONVERT(date,#Date,108))
and Log_TB.Date >= #date1 and User_TB.User_Branch = 'Pune'
group by Log_TB.Date;
My table definition
CREATE TABLE [dbo].[Log_TB]
(
[User_Id] [varchar](50) NOT NULL,
[First_Login] [time](0) NULL,
[Logout] [time](0) NULL,
[Date] [date] NULL,
[Working_Hrs] [time](0) NULL,
[extra_Int] [int] NOT NULL,
[extra_String] [varchar](50) NULL
)
What you need is a Numbers or a Date table. You can generate it using something like this
DECLARE #date1 DATE = '20150401',#Date DATE= GETDATE();
;WITH CTE AS
(
SELECT #date1 as datecol
UNION ALL SELECT DATEADD(day,1,datecol) FROM CTE WHERE DATEADD(day,1,datecol) <= #Date
)
SELECT * FROM CTE
In your query, you would use it like this
Declare
#Date date = GETDATE(),
#date1 date,
#Total int
set #date1 = (CONVERT(date,DATEADD(DD,-6,#Date),108));
select #Total = Count(User_TB.User_Id)
from User_TB join Branch_TB
on User_TB.User_Branch = Branch_TB.Branch_Name
where User_TB.User_Branch = 'Pune';
DECLARE #date1 DATE = '20150401',#Date DATE= GETDATE();
;WITH CTE AS
(
SELECT #date1 as datecol
UNION ALL SELECT DATEADD(day,1,datecol) FROM CTE WHERE DATEADD(day,1,datecol) <= #Date
)
select convert(varchar,CTE.datecol,106) AS Date,
CONVERT(CHAR(3),DATENAME(weekday,CTE.datecol)) AS Day,
#Total AS Total,COUNT(User_TB.User_Id) Present,
(#Total-COUNT(User_TB.User_Id)) AS Absent
From CTE LEFT JOIN Log_TB ON Log_TB.Log_TB.Date = CTE.datecol
LEFT join User_TB on Log_TB.User_Id = User_TB.User_Id
and User_TB.User_Branch = 'Pune'
group by CTE.datecol;
Declare #date datetime -- its a starting date
Set #Date = '1-Apr-2015'
Declare #table table (date datetime)
-- inserts data from starting date till getdate
while #date <> convert(datetime,convert(varchar(10),getdate(),101),101)
begin
insert into #table
select #date aa
select #date = #date+1
end
select * from #table
Just join #table and your data with left join
Select *
from #table left join (Your data) with condition date.
USE databasename
GO
CREATE function fx_explodedates_by date
( #datestart smalldatetime,
#dateend smalldatetime )
RETURNS #daterange TABLE
(
tenant id nchar(5),
salutation nchar(10)
forename nvarchar(20)
surname nvarchar(20)
startdate (yyyy-mm-dd)
enddate (yyyy-mm-dd)
)
AS
BEGIN
INSERTt #daterange
SELECT tenant id, salutation, forename,surname,startdate,enddate
FROM tablename
WHERE date between #datestart and #dateend
END
Assuming this is for SQL Server (based on syntax) your function is almost correct - apart from typographical errors and datatype syntax errors you're just missing a return statement.
The function should probably look something like this:
CREATE function fx_explodedates_by_date
( #datestart smalldatetime,
#dateend smalldatetime )
RETURNS #daterange TABLE
(
tenant_id nchar(5),
salutation nchar(10),
forename nvarchar(20),
surname nvarchar(20),
startdate date,
enddate date
)
AS
BEGIN
INSERT #daterange (tenant_id, salutation, forename, surname, startdate, enddate)
SELECT tenant_id, salutation, forename, surname, startdate, enddate
FROM tablename
WHERE [date] between #datestart and #dateend
RETURN
END
It's a bit unclear what your table actually looks like so you will probably have to change the column names and types to match what they're actually are (I was guessing a bit).
I have 5 tables: Location, Charge, Resource, Roster and SpecialRoster.
CREATE TABLE Location(
LocationID int identity,
StartDate datetime,
DaysInRoster int)
CREATE TABLE Charge(
ChargeID int identity,
TotalAmount money,
ChargeDate datetime,
UserID int)
CREATE TABLE [Resource](
ResourceID int identity,
ResourceName varchar(100))
CREATE TABLE Roster(
RosterDay int,
ResourceID int,
StartDate datetime,
EndDate datetime,
UserID int)
CREATE TABLE SpecialRoster(
RosterDate datetime,
ResourceID int,
UserID int)
I need to construct a report which shows the sum of Charge.TotalAmount on different days, by ResourceID.
Charge only has a UserID, but the rules are fairly simple:
If the date and ResourceID is in SpecialRoster, the UserID is taken from SpecialRoster
If not, the UserID for the Resource and the RosterDay for the date is taken from the Roster current at that time
Basically, I need to map ResourceID, through UserID from Roster or SpecialRoster, to Charge.
The RosterDay is the current day of the roster, and can be calculated from location, where the RosterDay = DateDiff(day, Location.RosterStartDate, GetDate()) % Location.DaysInRoster
that is, the modulus of the difference between the start of the entire roster at that location, with the number of days in a roster period.
I have written a Function to do this:
CREATE FUNCTION dbo.GetRosteredUser
(
#ResourceID int,
#Date datetime,
#LocationID int
)
RETURNS int
AS
BEGIN
DECLARE #UserID int
DECLARE #RosterOffset int
Select #UserID = UserID from SpecialRoster Where ResourceID = #ResourceID and RosterDate = #Date
If #UserID is NOT NULL
return #UserID
else
Select #RosterOffset = DATEDIFF(day, StartDate, #Date) % DaysInRoster
from Location Where LocationID = #LocationID
Select #UserID = UserID from Roster Where ResourceID = #ResourceID and RosterDay = #RosterOffset
and ( #Date between StartDate and EndDate or #Date > StartDate and EndDate is NULL)
return #UserID
END
GO
But the function isn't great as it is slow, and only allows the report to be run for a single day at a time:
Select a.ResourceID, Name, a.UserID, Sum(c.TotalAmount ) as AmountCharged
from Charge c
left outer join (
Select ResourceID, Name,
dbo.GetUserByResourceDate(ResourceID, '1/FEB/2013', 1) as UserID
from [Resource]) a
on c.UserID = a.UserID
Where ChargeDate between '1/FEB/2013' and '2/FEB/2013'
group by a.ResourceID, Name, a.UserID
Is there a better way to do this? A User will want to run this to compare productivity of a resource over a period of time. eg:
Date ResourceID Name UserID TotalAmount
01/FEB/2013 1 Sales1 22 $1024
02/FEB/2013 1 Sales1 11 $1454
03/FEB/2013 1 Sales1 14 $1900
04/FEB/2013 1 Sales1 23 $3045
Perhaps, something like this might be of help:
SELECT
re.ResourceID,
re.ResourceName,
ch.UserID,
AmountCharged = SUM(ch.TotalAmount)
FROM
Location lo
CROSS JOIN Charge ch
CROSS APPLY (
SELECT DATEDIFF(DAY, lo.StartDate, ch.ChargeDate) % lo.DaysInRoster
) x (RosterDay)
INNER JOIN
[Resource] re
LEFT JOIN Roster ro
ON
ro.RosterDay = x.RosterDay
AND ch.ChargeDate BETWEEN ro.StartDate
AND ro.RecourceID = re.ResourceID
LEFT JOIN SpecialRoster sr
ON
sr.RosterDate = ch.ChargeDate
AND sr.RecourceID = re.ResourceID
ON
ch.UserID = ISNULL(sr.UserID, ro.UserID)
GROUP BY
re.ResourceID,
re.ResourceName,
ch.UserID
WHERE
lo.LocationID = #LocationID
AND ch.ChargeDate BETWEEN ...
;
In the above script, it is assumed that all datetime values are in fact only dates.
Also, I was somewhat surprised not to found a connection between Location and any of the other tables specified. If there is one and you simply forgot to mention it, please let me know if you need any help with incorporating the necessary condition(s) into the script.