I want to calculate the number of leave days taken for staff in the financial year (1 July 2017 to 30 June 2018).
Some staff apply for leave outside these days and it overlaps for example a staff member may have a leave application of -start date of 30/06/2017 to 03/07/2017, so that is 2 days, but I would need to capture just the 1 day in July 2017.
I just want to be 100% here, so here is my query below
Select * from leave where leave_start < '2018-07-01' and leave_end > '2017-06-30'
The table is
Staffno | leave_type | leave_start | leave_end | days_taken
0001 | AnnualLeave| 30/06/2017 | 03/07/2018 | 2
Obviously once I get the result I will need to work out the actual start and actual end date and then do a networkdays formula in excel for it.
Thanks, your help is much appreciated :)
Use CASE statement to substitute boundary dates if start and end dates are out of interval. In your example you don't count start and end date as a leave so if you need this in the query (here start and end days are counted as a leave) just add "-2" into period_days_taken definition:
Select leave.*,
DATEDIFF(DAY,
CASE WHEN leave_start<'2017-06-30'
THEN '2017-06-30'
ELSE leave_start END,
CASE WHEN leave_end>'2018-07-01'
THEN '2018-07-01'
ELSE leave_end END)
AS period_days_taken
from leave
WHERE leave_start <= '2018-07-01'
AND leave_end >= '2017-06-30'
SQLFiddle demo
Related
If you have table like this:
Name
Data type
UserID
INT
StartDate
DATETIME
EndDate
DATETIME
With data like this:
UserID
StartDate
EndDate
21
2021-01-02 00:00:00
2021-01-02 23:59:59
21
2021-01-03 00:00:00
2021-01-04 15:42:00
24
2021-01-02 00:00:00
2021-01-06 23:59:59
And you want to calculate number of users that is represented on each day in a week with a result like this:
Year
Week
NumberOfTimes
2021
1
8
2021
2
10
2021
3
4
Basically I want to to a Select like this:
SELECT YEAR(dateColumn) AS yearname, WEEK(dateColumn)as week name, COUNT(somecolumen)
GROUP BY YEAR(dateColumn) WEEK(dateColumn)
The problem I have is the start and end date if the date goes over several days I want it to counted each day. Preferably I don't want the same user counted twice each day. There are millions of rows that are constantly being deleted and added so speed is key.
The database is MS-SQL 2019
I would suggest a recursive CTE:
with cte as (
select userid, startdate, enddate
from t
union all
select userid, startdate,
enddate
from cte
where startdate < enddate and
week(startdate) <> week(enddate)
)
select year(startdate), week(startdate), count(*)
from cte
group by year(startdate), week(startdate)
option (maxrecursion 0);
The CTE expands the data by adding 7 days to each row. This should be one day per week.
There is a little logic in the second part to handle the situation where the enddate ends in the same week as the last start date. The above solution assumes that the dates are all in the same year -- which seems quite reasonable given the sample data. There are other ways to prevent this problem.
You need to cross-join each row with the relevant dates.
Create a calendar table with columns of years and weeks, include a start and end date of the week. See here for an example of how to create one, and make sure you index those columns.
Then you can cross-join like this
SELECT
YEAR(dateColumn) AS yearname,
WEEK(dateColumn)as weekname,
COUNT(somecolumen)
FROM Table t
JOIN CalendarWeek c ON c.StartDate >= t.StartDate AND c.EndDate <= t.EndDate
GROUP BY YEAR(dateColumn), WEEK(dateColumn)
I have a table:
1 180101 180228
2 180301 180831
3 180901 999999
4 180801 999999
5 180401 181031
6 181101 999999
7 180101 999999
The columns are: userid, start date, end date.
Dates are in text format, YYMMDD with 999999 meaning that there is no end date.
How do I get the number of customers for each month? Ex. March would include all customers that start on or before March, and end on or after March. But would not include customers that started in January, but ended in February.
I'm trying to do it like this, and then write out all the logic:
SELECT SUBSTRING(start_date, 3, 2) AS start, SUBSTRING(end_date, 3, 2) AS end, count(*)
FROM data
GROUP BY start, end
ORDER BY start
Was just wondering if there was any better way to do it?
If you had starts in every month, you can use correlated subqueries to get the count on the first day of the month:
select ym.yymm,
(select count(*)
from t
where t.startdate <= ym.yymm and
t.enddate >= ym.yymm
) as month_count
from (select distinct left(startdate, 4) as yymm
from t
) ym;
Some databases might spell left() as substr().
I'm creating a system to calculate user working days.
Suppose user 1 has been at work from 2020-02-01 to 2020-02-20.
And user 2 has been at work from 2020-02-10 to 2020-02-15
In Sql Server
I have something similar in the table below
Now i want to calculte count of user working days between 2 date
For Example
Select Sum(DateDiff(Day,StartDate,EndDate)) From Table1 Where StartDate >= '2020-02-08' And EndDate <= '2020-02-12'
Above query returns 0 . But in this date user 1 has 5 working days and user 2 has 3 working days.
How can i calculate this?
I want a similar answer below:
You can use datediff() -- after testing for the limits of the period that you want:
select t.*,
datediff(day,
case when startdate < '2020-02-08' then '2020-02-08' else startdate end),
case when enddate > '2020-02-12' then '2020-02-12' else startdate end)
) + 1
from t;
The + 1 is because you are including the last day in the calculation.
Note: This only works correctly when there is an overlap. You want a filter:
(enddate >= '2020-02-08' or startdate <= '2020-02-12')
Based on the question, I'm not sure if this should be in a WHERE clause or a CASE expression. That is, do you want to filter out non-overlaps or do you want them to appear as 0/NULL?
For my project, I need to find a query which find data of upcoming 30 days with 1 year more.
Here's an example :
-I did a training the 2014-01-31 and to complete my training I need to do a reminder 1 year after (2015-01-31).
-BUT, I want to select this reminder in my database, 30 days minimum before the date of the reminder.
-SO, my goal is to have a reminder from the 2015-01-31 until to 2015-01-31.
Here's an example of my code, because of my bad English (I'm french IT student), I can't explain really good... :/
select nom, libelle_produit, nom_produit, date_debut_formation, date_fin_formation,
DATEADD (day , 365 , date_fin_formation) as 'Date limite'
from T_PRODUIT
join T_FORMATION on T_FORMATION.id_produit=T_PRODUIT.id_produit
join T_SUIT on T_SUIT.id_formation=T_FORMATION.id_formation
join T_EMPLOYES on T_EMPLOYES.id_employe = T_SUIT.id_employe
where DATEADD(year,1,year(date_fin_formation)) <= DATEADD(year,1,getdate())
and DATEADD(month,1,month(date_fin_formation)) <= DATEADD(month,1,getdate())
and DATEADD (day,1,day(date_fin_formation)) <= DATEADD(day,-30,GETDATE())
Could you help me please ? This don't give me a good result...
If I understand your question correctly, you want
All Reminders to be shown today if
date_fin_formation is less than (Today's date - 1 yr) + 30 days
date_fin_formation is greater than Today's date - 1 yr
i.e. notification should start from (Today's date - 1 yr) + 30 days and end till (Today's date - 1 yr)
You can use a WHERE clause like DATEADD(year,1,date_fin_formation) BETWEEN DATEADD(day,-30,getdate()) AND GETDATE() and Your Query would be.
select nom, libelle_produit, nom_produit, date_debut_formation, date_fin_formation, DATEADD (day , 365 , date_fin_formation) as 'Date limite'
from T_PRODUIT
join T_FORMATION on T_FORMATION.id_produit=T_PRODUIT.id_produit
join T_SUIT on T_SUIT.id_formation=T_FORMATION.id_formation
join T_EMPLOYES on T_EMPLOYES.id_employe = T_SUIT.id_employe
WHERE DATEADD(year,1,date_fin_formation) BETWEEN DATEADD(day,-30,getdate()) AND GETDATE()
Patient Code Unique Visit Code AdmitDate Discharge Date
91260 10146440 7/20/2013 9/16/2013
91260 10217043 9/21/2013 11/2/2013
This is a single patient with 2 different visits to the physician, I need to take the Discharge date of the earliest visit (9/16/2013) and the AdmitDate of the most recent visit (9/21/2013) and determine if it's within a 30 day period. How do I accomplish this in SQL 2008
Try
SELECT PATIENT_CODE,
CASE WHEN DATEDIFF(DAY, MIN(DISCHARGE_DATE), MAX(ADMIT_DATE)) < 30 THEN 1 ELSE 0 END
FROM TABLE1
GROUP BY PATIENT_CODE
The code
CASE WHEN DATEDIFF(DAY, MIN(DISCHARGE_DATE), MAX(ADMIT_DATE)) < 30 THEN 1 ELSE 0 END
will be 1 for those visits which occurs in period less than 30 days.
SQL Fiddle