Count numbers of days worked for Employees in SQL Server - sql

I have a database containing transactional data. I am trying to count the number of days all employees worked between '2016-03-01' and '2017-03-01'. What I am using to determine the days worked per employee is by doing a count(distinct day(datecompleted)) where datecompleted resembles a day that an employee completed an activity as the driver.
The issue is there can be 50-100 transactions a day each having a datecompleted time stamp, however I just want to check if the employee worked that day by grabbing a distinct day(datecompleted) and then counting how many between the given time frame...
I used this query:
select
count(distinct day(dateCompleted)),
repName
from
DATABASE_view_Final
where
datecompleted between '2016-03-01' and '2017-03-01'
group by
repName
For some reason I keep getting the result : 31....
which doesn't make any sense...someone please help

Your counting distinct days (1-31) NOT dates. Perhaps you could try:
select count(distinct cast(dateCompleted as date)),
repName
from DATABASE_view_Final
where datecompleted between '2016-03-01' and '2017-03-01'
group by repName

Related

Data value on a given date

This time I have a table on a PostgreSQL database that contains the employee name, the date that he started working and the date that he leaves the company, in the cases of the employee still remains in the company, this field has null value.
Knowing this, I would like to know how many people was working on a predetermined date, ex:
I would like to know how many people works on the company in January 2021.
I don't know where to start, in some attempts I got the number of hires and layoffs per month, but I need to show this accumulated value per month, in another column.
I hope I made myself understood, I'll leave the last SQL I got here.
select reference, sum(hires) from
(
select
date_trunc('month', date_hires) as reference,
count(*) as hires
from
ponto_mais_relatorio_colaboradores
group by
date_hires
union all
select
date_trunc('month', date_layoff) as reference,
count(*)*-1 as layoffs
from
ponto_mais_relatorio_colaboradores
group by
date_layoff
) as reference
join calendar_aux on calendar_aux.ano_mes = reference
group by reference
order by reference
Break the requirement down. The question: how many are employed on any given date? That would include all hired before that date and do not have a layoff date plus all hired before with a layoff date later then the date your interested period. I.e you are interested in Jan so you still want to count an employee with a layoff date in Feb. With that in place convert into SQL. The preceding is available from select comparing dates. other issue is that Jan is not a date, it is a range of dates, so you need each date. You can use generate series to create each day in Jan. Then Join the generated dates with and selection from your table. Resulting query:
with jan_dates( jdate ) as
( select generate_series( date '2021-01-01'
, date '2021-01-31'
, interval '1' day
)::date
)
select jdate "Date", count(*) "Employees"
from jan_dates j
join employees e
on ( e.date_hires <= j.jdate
and ( e.date_layoff is null
or e.date_layoff > j.jdate
)
)
group by j.jdate
order by j.jdate;
Note: Not tested.

SQL get distinct customer count by hour

I have two table with datein and timein that is recorded when an order is placed and another table with the column datepicked and timepicked that is recorded when the invoice from the order is picked up. I need to find out how many customer I have every hour, but some are placing order and some are picking up invoices and some are doing both. There could be more than one order and invoice for the same customer on the same day/hour.
OrderTable:
Ordernum
CustomerID
datein
timein
InvoiceTable:
CustomerID
InvoiceID
Ordernum
datepicked
timepicked
I tried this SQL, but I can't find out how to get the DISTINCT CUSTOMERID from both tables and the date and hours lined up on both tables, I noticed in the result if there was no order for one hour / day the columns did not lineup.
Select o.datein, i.datepicked, (o.datein) As iDay, HOUR(o.timein) as iH,
DayOfMonth(i.datepicked) As pDay, HOUR(i.timepicked) as pH, Count(*) as Total
from OrderTable o, InvoiceTable i
Where
o.datein >= '2019-01-01' and o.datein <= '2019-12-31'
GROUP BY o.datein, i.datepicked, iDay, iH, pDay, pH
Thanks for any help.
Kim
Not sure why the tables setup as they are, but if all you really care about is the DISTINCT customer per date/hour, I would do the following by pre-unioning just those records, then distinct count from that. Dont worry about joining if the transactions were done at separate times unless your consideration is that the order and invoice are BOTH handled within the same hour. What happens if one order is done at 10:59 and the invoice is 11:00 only 1 minute apart, but representative of 2 different hours. It would be the same 1 customer showing up in each individual hour component.
Notice the first "FROM" clause has a union to get all records to the same column name bulk of records, each of their own respective 2019 calendar activity date. Once that is done, get and group by for the COUNT DISTINCT customers.
select
AllRecs.DateIn,
hour( AllRecs.TimeIn ) ByHour,
DayOfMonth(AllRecs.DateIn) pDay,
Count( distinct AllRecs.CustomerID ) UniqueCustomers
from
( select
ot.CustomerID,
ot.datein,
ot.timein
from
OrderTable ot
where
ot.datein >= '2019-01-01'
and ot.datein <= '2019-12-31'
union all
select
it.CustomerID,
it.datepicked datein,
it.timepicked timein
from
InvoiceTable it
where
it.datepicked >= '2019-01-01'
and it.datepicked <= '2019-12-31' ) AllRecs
group by
AllRecs.DateIn,
hour( AllRecs.TimeIn ),
DayOfMonth(AllRecs.DateIn)
If you had a relation between these two tables it would be possible. If I understand what you are trying to do, InvoiceTable needs to be a child table of OrderTable with a foreign key field "OrderNum" that relates back to its parent "OrderTable" primary key "OrderNum". Therefore, you don't need a field "CusotmerID" on InvoiceTable and you would know when an Invoice been picked up belongs to an order from the same day.

Count Number of hours between a range SQL

Im trying to count the number of working hours from some users for the month, the only way to do it is to see the date and hour for the productions entries they made. so I got:
Select a.EmployeeID, cast(a.fDate as Date) fDate, datepart(HOUR, a.fDate) fHour
From Table
Group by a.EmployeeID, cast(a.fDate as Date), datepart(HOUR, a.fDate)
This gives me the detail by date of the hours production was done, however I would like to know the total of hours in that time frame. For example:
I know employee xxx on 09/01/2018 registered production at 10:00AM, 11:00AM 12:00PM and 1:00PM, so the result will be 4 hours. Every employee has different working days so thats the only way I think I can calculated this...
Help?
Can you use the DATEDIFF of the min and max of fDate, group by EmployeeId and Date of a.fDate?
For example:
Select a.EmployeeID, cast(a.fDate as Date) as fDate, min(a.fDate) as TimeIn, max(a.fDate) as TimeOut, (DATEDIFF(mi, min(a.fDate), max(a.fDate)) / 60) as Hours
From MyTable a
Group by a.EmployeeID, cast(a.fDate as Date)

SQL Server one-to-many relational IF query

I have an employees table that has many employee_records. The employee_records table has a column named event_type and it is an enum that can be either hire-date, promotion, termination, title-change, or rehire. I am attempting to calculate an employees total time employed and make some calculations based on how long they have been employed.
How can I add a column that gives me the total days that they have been employed?
Essentially, I need to see if they have a record with the event_type = termination and if they do, then I need to see if they have a rehire date, and if they do, then I need to use their rehire date as the first day of their employment and calculate their time of employment that way.
As for a result, I simply need a days_employed column that reflects the actual amount of days they have been employed.
Here is what I have so far.
SELECT
employees.id,
first_name,
last_name,
email,
event_type,
CASE
WHEN DATEDIFF(DAY, employee_records.created_at, SYSDATETIME()) < 365 * 5
THEN 1
WHEN DATEDIFF(DAY, employee_records.created_at, SYSDATETIME()) < 365 * 10
THEN 2
ELSE 3
END AS benfits_type,
DATEDIFF(DAY, employee_records.created_at, SYSDATETIME()) AS days_employed,
employee_records.created_at AS hire_date
FROM
employees
JOIN
employee_records ON employees.id = employee_records.employee_id
ORDER BY
employees.id ASC;
Here is an example of how you could do this. I'll post the query first and then walk through my explanation. If I understood you correctly, you were not looking for total days the employee was hired, but rather the total days of the employee's most recent employment at the company (Max hire date to max termination date or today).
;WITH hired
AS (SELECT employee_records.employee_id id,
Max(employee_records.created_at) created_at
FROM employee_records
WHERE event_type = 'hire-date'
GROUP BY employee_records.employee_id),
latest
AS (SELECT employees.id
id,
Isnull(Cast(Max(employee_records.created_at) AS DATE), Getdate()
)
created_at
FROM employees
LEFT JOIN employee_records
ON employees.id = employee_records.employee_id
AND employee_records.event_type = 'termination'
GROUP BY employees.id)
SELECT *,
Datediff(day, hired, latestday) DaysEmployeed
FROM (SELECT hired.id,
hired.created_at AS Hired,
CASE
WHEN hired.created_at > latest.created_at THEN Cast(
Getdate() AS DATE)
ELSE latest.created_at
END AS LatestDay
FROM hired
INNER JOIN latest
ON hired.id = latest.id) JoinedCTEs
First of all I know you mentioned event_type is an integer, but for easy explanation I used a varchar.
Two CTEs to start.
First there is "hired" which will get you the latest hire date. So if an employee has multiple hire dates, it grabs the latest date.
Second there is "latest" which is the latest date an employee has a termination date, but also uses today's date as a placeholder date if an employee has never been terminated.
The final query joins the two CTEs and does a datediff by day to determine how many days an employee has been at the company. If the termination date is earlier than the hire date (An employee who was hired, terminated, rehired and is still with the company), it will take today's date as the latest date to count.

Number of Unique Visits in SQL

I am using Postgres 9.1 to count the number of unique patient visits over a given period of time, using the invoices entered for each patient.
I have two columns, transactions.ptnumber and transactions.dateofservice, and can calculate the the patient visits in the following manner:
select count(*)
from transactions
where transactions.dateofservice between '2012-01-01' and '2013-12-31'
The problem is that sometimes one patient might get two invoices for the same day, but that should be counted as only one patient visit.
If I use SELECT DISTINCT or GROUP BY on the column transactions.ptnumber, that would count the number of patients who were seen (but not the number of times they were seen).
If I use SELECT DISTINCT or GROUP BY on the column transactions.dateofservice, that would count the number of days that had an invoice.
Not sure how to approach this.
This will return unique patients per day.
select count(distinct transactions.ptnumber) as cnt
from transactions
where transactions.dateofservice between '2012-01-01' and '2013-12-31'
group by transactions.dateofservice
You can sum them up to get the unique patients for the whole period
select sum(cnt) from (
select count(distinct transactions.ptnumber) as cnt
from transactions
where transactions.dateofservice between '2012-01-01' and '2013-12-31'
group by transactions.dateofservice
)
You might use a subselect, consider
Select count(*)
from (select ptnumber, dateofservice
from transactions
where dateofservice between '2012-01-01' and '2013-12-31'
group by ptnumber, dateofservice
)
You may also want to make this a stored procedure so you can pass in the date range.
There are multiple ways to achieve this, but you could use the WITH clause to construct a temporary table that contains the unique visits, then count the results !
WITH UniqueVisits AS
(SELECT DISTINCT transactions.ptnumber, transactions.dateofservice
FROM transactions
WHERE transactions.dateofservice between '2012-01-01' and '2013-12-31')
SELECT COUNT(*) FROM UniqueVisits