The scenario is: I have a workflow in which an object passes through multiple stages until it's closed (end of process). In this case, I have a table with the unique Id of this object, the day it arrived in a given stage, and the day it left this same stage. The calculation of "total days in stage X" must NOT consider weekends and holidays (which is an info that comes from a different calendar table).
Id
first time at stage
last time at stage
01
2021-09-02
2021-09-09
So in between those dates, we have a weekend and 2 holidays here in my country, which means the proper time in stage would be 3.
In paralel, I created a table with the dates of all weekends and holidays of the year (it's just one column "date"), with the intention of basically counting the days in this table that would be in between "first time at stage" and "last time at stage", in order to subtract it from the final datediff.
So I have:
SELECT DISTINCT
id,
first_time_stage,
last_time_stage,
DATE_DIFF(last_time_stage,first_time_stage,DAY) - COALESCE(
(SELECT COUNT(1)
FROM base_holidays_and_weekends c
LEFT JOIN base_stage_periods p ON c.date = p.first_time_at_steage AND c.date = p.last_time_stage
WHERE date BETWEEN first_time_stage AND last_time_stage), 0) AS time_spent_in_stage
Where am I getting it wrong? I assume the issue is having 2 different tables, or in the JOIN... :(
Thank you for any inputs!
Related
I'm looking to create a recurring date calculator that will correspond to EVENTS on a specific calendar date. Each event has its own rule.
For example, for EVENT A rule is "Occurs Tuesday monthly with the start date Tuesday 9-17-2019. I'm using a time dimension table with every date populated until 2025. Using these dates I was using in the WHERE clause
WHERE dayname = 'tuesday' and ( DATEDIFF(DAY, '2019-09-17', Calendar_Date) % 28 ) = 0 to get monthly tuesdays.
But I'm running into issues when there are two 5 Tuesdays in a month. 3-3-2020 and 3-31-2020. Need date populated to be 4-7-2020 instead of 3-31-2020.
Can anyone help with a solution?
With your query, you're pretty close. All you need to do is to then sub-select
SELECT MIN(CalendarDate) AS CalendarDate
FROM (your query goes here) AS d
GROUP BY YEAR(CalendarDate), MONTH(CalendarDate);
I want data for customers for last three months from there deactivation date
So I joined two tables
One table have data like recharge, Report_Month
Other table have deactivation date
Both table have mobile number column
So I have condition in where clause
Disconnection date between 2019-05-07 and 2019-08-10
And
Report month between ?????
So I have trouble in Report month condition
Report month data like 1,2,3 upto 12
So I want data between disconnection date and before three months of disconnection date
Sorry, I'm having trouble understanding your question, I think you're asking how to select the last three months worth of data from a disconnection date. If so you'll need a condition like:
WHERE `Report_Month` >= DATEADD(MONTH, -3, `Disconnection_date`)
So this will return everything with a report month up to three months before disconnection date.
The second part confuses me more, I think you're asking to group the report month, up to 12 months, but, if you're only retrieving the last three months data, then how could you group by 12?
GROUP BY Year(`Report_Month`), Month(`Report_Month`)
ORDER BY Year(`Report_Month`), Month(`Report_Month`)
That will group your results by Month in order, if that's what you're after?
I am looking for a query which gives me the daily playing time. The start (first_date) and end date(last_update) are given as shown in the Table. The following query gives me the sum of playing time on given date. How can I extend it to get a table from first day to last day and plot the query data in it and show 0 on dates when no game is played.
SELECT startTime, SUM(duration) as sum
FROM myTable
WHERE startTime = endTime
GROUP BY startTime
To show date when no one play you will need create a table days with a date field day so you could do a left join. (100 years is only 36500 rows).
Using select Generate days from date range
This use store procedure in MSQL
I will assume if a play pass the midnight a new record begin. So I could simplify my code and remove the time from datetime field
SELECT d.day, SUM(duration) as sum
FROM
days d
left join myTable m
on CONVERT(date, m.starttime) = d.day
GROUP BY d.day
If I understand correctly, you could try:
SELECT SUM(duration) AS duration, date
FROM myTable
WHERE date <= 20140430
AND date => 20140401
GROUP BY date
This would get the total time played for each date between april 1 and april 30
As far as showing 0 for dates not in the table, I don't know.
Also, the table you posted doesn't show a duration column, but the query you posted does, so I went ahead and used it.
I have a course calendar events table as follows (showing only a few records for simplicity):
calendarItemID classID startDate startTime endTime
----------------------------------------------------------
1 1 2011-11-24 7pm 9pm
2 2 2011-11-02 7pm 9pm
3 1 2011-11-25 7pm 9pm
I need a query that returns courses for the UPCOMING QUARTER (not the current quarter). Is there a SQL function that can help and/or is this a case of working out the dates in the current quarter and seeing if StartDate fits within those dates. I'm looking for the most elegant way if possible.
Thanks in advance!
Paul
Straightforward, but slow approach :
WHERE DATEPART(qq,startDate) = DATEADD(qq, 1,GETDATE()) AND YEAR(startDate) =
YEAR(DATEADD(qq, 1,GETDATE()))
By slow I mean that even if you have an index on (startDate) it won't be used.
The better solution is to get start_date and end_date for the next quarter. I can see a number of ways to do so. For instance, you can create 2 scalar UDF that returns start_date and end_date respectively. You can also create 1 table-valued function that returns 1 row with 2 columns and then join it. Finally, you can just create a lookup table and manually enter start/end date for next couple of years.
Create a table called say Quarters with a useful ID say YYYYQQ, and a start and end date, then it's a simple join.
I have an interesting query to do and am trying to find the best way to do it. Basically I have an absence table in our personnel database this records the staff id and then a start date and end date for the absence. End date being null if not yet entered (not returned). I cannot change the design.
They would like a report by month on number of absences (12 month trend). With staff being off over the month change it obviously may be difficult to calculate.
e.g. Staff off 25/11/08 to 05/12/08 (dd/MM/yy) I would want the days in November to go into the November count and the ones in December in the December count.
I am currently thinking in order to count the number of days I need to separate the start and end date into a record for each day of the absence, assigning it to the month it is in. then group the data for reporting. As for the ones without an end date I would assume null is the current date as they are presently still absent.
What would be the best way to do this?
Any better ways?
Edit: This is SQL 2000 server currently. Hoping for an upgrade soon.
I have had a similar issue where there has been a table of start/end dates designed for data storage but not for reporting.
I sought out the "fastest executing" solution and found that it was to create a 2nd table with the monthly values in there. I populated it with the months from Jan 2000 to Jan 2070. I'm expecting it will suffice or that I get a large pay cheque in 2070 to come and update it...
DECLARE TABLE months (start DATETIME)
-- Populate with all month start dates that may ever be needed
-- And I would recommend indexing / primary keying by start
SELECT
months.start,
data.id,
SUM(CASE WHEN data.start < months.start
THEN DATEDIFF(DAY, months.start, data.end)
ELSE DATEDIFF(DAY, data.start, DATEADD(month, 1, months.start))
END) AS days
FROM
data
INNER JOIN
months
ON data.start < DATEADD(month, 1, months.start)
AND data.end > months.start
GROUP BY
months.start,
data.id
That join can be quite slow for various reasons, I'll search out another answer to another question to show why and how to optimise the join.
EDIT:
Here is another answer relating to overlapping date ranges and how to speed up the joins...
Query max number of simultaneous events