I have a date table where I have assinged business days. I need to get business from, for example, 1-20 before the next number 1. How can I do that? Here is a smaller verion of my table:
Date Day BusinessDays
2015-05-01 Friday 1
2015-05-02 Saturday 2
2015-05-03 Sunday 2
2015-05-04 Monday 2
2015-05-05 Tuesday 3
2015-05-06 Wednesday 4
2015-05-07 Thursday 5
2015-05-08 Friday 6
2015-05-09 Saturday 7
2015-05-10 Sunday 7
2015-05-11 Monday 7
2015-05-12 Tuesday 8
2015-05-13 Wednesday 9
2015-05-14 Thursday 10
2015-05-15 Friday 11
2015-05-16 Saturday 12
2015-05-17 Sunday 12
2015-05-18 Monday 12
2015-05-19 Tuesday 13
2015-05-20 Wednesday 14
2015-05-21 Thursday 15
2015-05-22 Friday 16
2015-05-23 Saturday 17
2015-05-24 Sunday 17
2015-05-25 Monday 17
2015-05-26 Tuesday 17
2015-05-27 Wednesday 18
2015-05-28 Thursday 19
2015-05-29 Friday 20
*2015-05-30 Saturday 1
*2015-05-31 Sunday 1
*2015-06-01 Monday 1
*2015-06-02 Tuesday 2
*2015-06-03 Wednesday 3
I need to get data from 1 to 20 business days and don't include the numbers that starts again from one (for example exclude rows that have * in front). This needs to be dynamic. Since DayName will change for every number so I can't include that in my where clause.
Let me assume that you have a date in mind, so you want everything from that date to the next "1".
select t.*
from datetable t
where t.date >= '2015-05-01' and
t.date < (select min(t2.date)
from datetable t2
where t2.date > '2015-05-01' and
t2.businessdays = 1
);
Related
Today/Getdate is always going to be the starting date. A counter starts at 0; let's call it TheResult. If the day is Friday/Saturday/Sunday/Monday, then they all receive the same number in the counting process. The accrual picks back up on Tuesday.
TheDate
TheDayName
TheResult
2022-06-07
Tuesday
0
2022-06-08
Wednesday
1
2022-06-09
Thursday
2
2022-06-10
Friday
3
2022-06-11
Saturday
3
2022-06-12
Sunday
3
2022-06-13
Monday
3
2022-06-14
Tuesday
4
2022-06-15
Wednesday
5
2022-06-16
Thursday
6
2022-06-17
Friday
7
2022-06-18
Saturday
7
2022-06-19
Sunday
7
2022-06-20
Monday
7
2022-06-21
Tuesday
8
What would the sql code need to be to achieve the values in the TheResult column?
I'm not sure how to approach the problem because of the Fri-Mon bucket of days, so I have not made any progress. I've tried finding similar questions asked using Google, but it seems I'm searching for the wrong keywords to find the answer to my question.
I have a table with just one column and about 3000 rows that follows the same pattern. I want to include the days of the week at the beginning of the string for each TIME inside the same string in the row.
Original table :
DATA_TIME_COMBINATION
Monday 3 am HM, 5 am HC, 10 pm HX
Saturday AB 6 am, WE 5 pm
Sunday Friday AN 50 TU,FG 55 RE, DC 56 JJ
Tuesday 10 am, 5 am, 1 am
Wednesday 12 pm-9 pm- 1 am
Results needed :
DATA_TIME_COMBINATION
Monday 3 am HM, Monday 5 am HC, Monday 10 pm HX
Saturday AB 6 am, Saturday WE 5 pm
Sunday Friday AN 50 TU, Sunday Friday FG 55 RE, Sunday Friday DC 56 JJ
Tuesday 10 am, Tuesday 5 am, Tuesday 1 am
Wednesday 12 pm- Wednesday 9 pm- Wednesday 1 am
Thanks in advance!
seems you want replace the comma with a comma and the first word at beginning of the string
select replace(DATA_TIME_COMBINATION, ',',
concat(',', substr(DATA_TIME_COMBINATION,1,charindex(' ', DATA_TIME_COMBINATION)-1)))
from my_table
Once you know the character and days.
Then it'll become a simple replace.
One cross apply for the weekdays.
A second for a character in place.
SELECT
REPLACE(REPLACE([DATA_TIME_COMBINATION], chr, chr+' '+days+' '),' ',' ') as DATA_TIME_COMBINATION
FROM mytable AS t
CROSS APPLY (
SELECT STRING_AGG(value, ' ') days
FROM STRING_SPLIT(
LEFT([DATA_TIME_COMBINATION], PATINDEX('%[a-z] [0-9]%', [DATA_TIME_COMBINATION])), ' ') spl
WHERE value LIKE '%day'
) ca1
CROSS APPLY (
SELECT
chr = SUBSTRING([DATA_TIME_COMBINATION], PATINDEX('%[^A-Za-z0-9 ]%', [DATA_TIME_COMBINATION]), 1)
) ca2;
DATA_TIME_COMBINATION
Monday 3 am HM, Monday 5 am HC, Monday 10 pm HX
Saturday AB 6 am, Saturday WE 5 pm
Sunday Friday AN 50 TU, Sunday Friday FG 55 RE, Sunday Friday DC 56 JJ
Tuesday 10 am, Tuesday 5 am, Tuesday 1 am
Wednesday 12 pm- Wednesday 9 pm- Wednesday 1am
Test on db<>fiddle here
I am using the following script to determine what the business days are for each particular month.
DECLARE #startdate DATETIME
SET #startdate ='20170401'
;
WITH bd AS(
SELECT
DATEADD(DAY,
CASE
(DATEPART(WEEKDAY, DATEADD(MONTH, DATEDIFF(MONTH, 0, #startdate), 0)) + ##DATEFIRST - 1) % 7
WHEN 6 THEN 2
WHEN 7 THEN 1
ELSE 0
END,
DATEADD(MONTH, DATEDIFF(MONTH, 0, #startdate), 0)
) AS bd, 1 AS n
UNION ALL
SELECT DATEADD(DAY,
CASE
(DATEPART(WEEKDAY, bd.bd) + ##DATEFIRST - 1) % 7
WHEN 5 THEN 3
WHEN 6 THEN 2
ELSE 1
END,
bd.bd
) AS db,
bd.n+1
FROM bd WHERE MONTH(bd.bd) = MONTH(#startdate)
)
SELECT * INTO #BD
FROM (
SELECT 'BD'+ CAST(n AS VARCHAR(5)) AS Expected_Date_Rule, bd AS Expected_Calendar_Date
from bd
) AS x
The result of this table works fine. Bd is the the calendar days for the particular month and n is the business day number. The script does its job of not counting the weekend as a business day.
bd n
----------------------- -----------
2017-04-03 00:00:00.000 1
2017-04-04 00:00:00.000 2
2017-04-05 00:00:00.000 3
2017-04-06 00:00:00.000 4
2017-04-07 00:00:00.000 5
2017-04-10 00:00:00.000 6
2017-04-11 00:00:00.000 7
2017-04-12 00:00:00.000 8
2017-04-13 00:00:00.000 9
2017-04-14 00:00:00.000 10
2017-04-17 00:00:00.000 11
2017-04-18 00:00:00.000 12
2017-04-19 00:00:00.000 13
2017-04-20 00:00:00.000 14
2017-04-21 00:00:00.000 15
2017-04-24 00:00:00.000 16
2017-04-25 00:00:00.000 17
2017-04-26 00:00:00.000 18
2017-04-27 00:00:00.000 19
2017-04-28 00:00:00.000 20
2017-05-01 00:00:00.000 21
But then I notice that a potential issue will occur in July where the output will count the 4th of July as BD2 when it should be counted as BD3. Some had created a holiday table that is updated with all the holidays (excuse the bad spelling).
Holiday table
1 2017-01-01 New Year Day
4 2017-01-02 New Year Day-Follow
1 2017-01-16 MArtin Luther King Day
4 2017-01-17 MArtin Luther King Day-Follow
1 2017-02-20 Preseiednt Day
4 2017-02-21 Preseiednt Day-Follow
1 2017-05-29 Memorial Day
4 2017-05-30 Memorial Day-Follow
1 2017-07-04 Independence Day
4 2017-07-05 Independence Day-Follow
1 2017-09-04 Labour Day
4 2017-09-05 Labour Day-Follow
1 2017-10-09 Columbus Day
4 2017-10-10 Columbus Day-Follow
1 2017-11-10 Vetrans Day
4 2017-11-11 Vetrans Day-Follow
1 2017-11-23 ThanksGiving
1 2017-11-24 Day After Thanks Giving
4 2017-11-24 ThanksGiving-Follow
4 2017-11-25 Day After Thanks Giving-Follow
1 2017-12-25 Christmas
4 2017-12-26 Christmas-Follow
I was thinking there may be some way I can update my script to check the holiday table and skip the holiday and dont count it as a business day. Any tips?
I'm looking to find the same day last year in oracle sql. For example Wednesday, March 16, 2016 would be Wednesday, March 18, 2015 for last year. So the closest day.
The following code worked good until the current leap year and broke after Feb 29th 2016.
this was my old statement which does not work for all dates:
NEXT_DAY(TRUNC(ADD_MONTHS(date, -12), 'iw')-2, TO_CHAR(date, 'DY'))
Simply subtract 7*52 = 364 days instead :-)
I think this may be correct
SQL Test:
WITH data
AS ( SELECT SYSDATE - (LEVEL - 1) this_year_date,
TO_NUMBER (TO_CHAR (SYSDATE - (LEVEL - 1), 'D'))
this_year_day_of_week,
ADD_MONTHS (SYSDATE - (LEVEL - 1), -12) last_year_date,
TO_NUMBER (
TO_CHAR (ADD_MONTHS (SYSDATE - (LEVEL - 1), -12), 'D'))
last_year_day_of_week
FROM DUAL
CONNECT BY LEVEL <= 300),
crunching
AS (SELECT data.*,
(CASE
WHEN this_year_day_of_week > last_year_day_of_week
THEN
this_year_day_of_week - last_year_day_of_week
WHEN this_year_day_of_week = last_year_day_of_week
THEN
0
ELSE
last_year_day_of_week - this_year_day_of_week
END)
math
FROM data)
SELECT TO_CHAR (crunching.this_year_date, 'yyyy-MM-dd Day') ty_date,
math,
(CASE
WHEN math = 0
THEN
TO_CHAR (last_year_date, 'yyyy-MM-dd Day')
WHEN math > 2
THEN
TO_CHAR ( (last_year_date - math) + 7, 'yyyy-MM-dd Day')
ELSE
TO_CHAR (last_year_date + math, 'yyyy-MM-dd Day')
END)
final_answer
FROM crunching
SQL Fiddle: http://sqlfiddle.com/#!4/9eecb7d/18211
Output:
TY_DATE MATH FINAL_ANSWER
2016-03-17 Thursday 2 2015-03-19 Thursday
2016-03-16 Wednesday 2 2015-03-18 Wednesday
2016-03-15 Tuesday 2 2015-03-17 Tuesday
2016-03-14 Monday 5 2015-03-16 Monday
2016-03-13 Sunday 5 2015-03-15 Sunday
2016-03-12 Saturday 2 2015-03-14 Saturday
2016-03-11 Friday 2 2015-03-13 Friday
2016-03-10 Thursday 2 2015-03-12 Thursday
2016-03-09 Wednesday 2 2015-03-11 Wednesday
2016-03-08 Tuesday 2 2015-03-10 Tuesday
2016-03-07 Monday 5 2015-03-09 Monday
2016-03-06 Sunday 5 2015-03-08 Sunday
2016-03-05 Saturday 2 2015-03-07 Saturday
2016-03-04 Friday 2 2015-03-06 Friday
2016-03-03 Thursday 2 2015-03-05 Thursday
2016-03-02 Wednesday 2 2015-03-04 Wednesday
2016-03-01 Tuesday 2 2015-03-03 Tuesday
2016-02-29 Monday 5 2015-03-02 Monday
2016-02-28 Sunday 6 2015-03-01 Sunday
2016-02-27 Saturday 1 2015-02-28 Saturday
2016-02-26 Friday 1 2015-02-27 Friday
2016-02-25 Thursday 1 2015-02-26 Thursday
2016-02-24 Wednesday 1 2015-02-25 Wednesday
2016-02-23 Tuesday 1 2015-02-24 Tuesday
2016-02-22 Monday 1 2015-02-23 Monday
2016-02-21 Sunday 6 2015-02-22 Sunday
2016-02-20 Saturday 1 2015-02-21 Saturday
2016-02-19 Friday 1 2015-02-20 Friday
2016-02-18 Thursday 1 2015-02-19 Thursday
2016-02-17 Wednesday 1 2015-02-18 Wednesday
How about add_months( [date], -12 ) ?
I have a following which are displayed order by date. I want to group each weekseries as below.
Select tq.ID,
CONVERT(VARCHAR(10),tq.DateCreated,101)WeekDate,
DATENAME(WEEKDAY,tq.DateCreated)WeekDays,
CASE When DATEPART(WEEKDAY,tq.DateCreated)-1=0 THEN 7 ELSE DATEPART(WEEKDAY,tq.DateCreated)-1 END as WeekSerial
From #temp tq
Current Data:
ID WeekDate WeekDays WeekSerial WeekNumber
56 2012-03-01 00:00:00.000 Thursday 4 NULL
57 2012-03-02 00:00:00.000 Friday 5 NULL
58 2012-03-03 00:00:00.000 Saturday 6 NULL
59 2012-03-04 00:00:00.000 Sunday 7 NULL
62 2012-03-05 00:00:00.000 Monday 1 NULL
63 2012-03-06 00:00:00.000 Tuesday 2 NULL
64 2012-03-07 00:00:00.000 Wednesday 3 NULL
65 2012-03-08 00:00:00.000 Thursday 4 NULL
67 2012-03-09 00:00:00.000 Friday 5 NULL
68 2012-03-10 00:00:00.000 Saturday 6 NULL
69 2012-03-11 00:00:00.000 Sunday 7 NULL
70 2012-03-12 00:00:00.000 Monday 1 NULL
71 2012-03-13 00:00:00.000 Tuesday 2 NULL
73 2012-03-14 00:00:00.000 Wednesday 3 NULL
74 2012-03-15 00:00:00.000 Thursday 4 NULL
76 2012-03-16 00:00:00.000 Friday 5 NULL
77 2012-03-17 00:00:00.000 Saturday 6 NULL
78 2012-03-18 00:00:00.000 Sunday 7 NULL
Required Data:
ID WeekDate WeekDays WeekSerial WeekNumber
56 2012-03-01 00:00:00.000 Thursday 4 1
57 2012-03-02 00:00:00.000 Friday 5 1
58 2012-03-03 00:00:00.000 Saturday 6 1
59 2012-03-04 00:00:00.000 Sunday 7 1
62 2012-03-05 00:00:00.000 Monday 1 2
63 2012-03-06 00:00:00.000 Tuesday 2 2
64 2012-03-07 00:00:00.000 Wednesday 3 2
65 2012-03-08 00:00:00.000 Thursday 4 2
67 2012-03-09 00:00:00.000 Friday 5 2
68 2012-03-10 00:00:00.000 Saturday 6 2
69 2012-03-11 00:00:00.000 Sunday 7 2
70 2012-03-12 00:00:00.000 Monday 1 3
71 2012-03-13 00:00:00.000 Tuesday 2 3
73 2012-03-14 00:00:00.000 Wednesday 3 3
74 2012-03-15 00:00:00.000 Thursday 4 3
76 2012-03-16 00:00:00.000 Friday 5 3
77 2012-03-17 00:00:00.000 Saturday 6 3
78 2012-03-18 00:00:00.000 Sunday 7 3
So, I want to group these values under weeknumber which must start from 1 for WeekSerial number ranges from 1 to 7.
NOTE: The week day starts from Monday to Sunday so its numbered from 1 through 7. i.e 1=Monday, 2=Tuesday and so on...!
Update:
INSERT INTO #Temp(KioskCount,KioskAmount,KioskAverage,WeekDate,WeekDays,WeekSerial)
Select COUNT(tq.quoteid)KioskCount,
SUM(tq.PriceQuote) [KioskAmount],
SUM(tq.PriceQuote) / COUNT(tq.QuoteID) [KioskAverage],
CONVERT(VARCHAR(10),tq.DateCreated,101)WeekDate,
DATENAME(WEEKDAY,tq.DateCreated)WeekDays,
CASE When DATEPART(WEEKDAY,tq.DateCreated)-1=0 THEN 7 ELSE DATEPART(WEEKDAY,tq.DateCreated)-1 END as WeekSerial
from tbl_Quotes tq
where
tq.QuoteStatusID <> 12 --remove void transactions
group by CONVERT(VARCHAR(10),tq.DateCreated,101),DATENAME(WEEKDAY,tq.DateCreated),DATEPART(WEEKDAY,tq.DateCreated)-1
order by 4
It is unclear actually what did you expect
You have already a WeekDate filed i think the date are correct and based on that you are filled your weekday field
then simply you can loop through the dates and update your week number using the WeekDate
i can provide an example with that
DECLARE #DATE DATETIME
DECLARE #count int
DECLARE #i int
SET #i=56// you can find your first id via query too
SET #count=(select COUNT(WeekDays) from tablename)
WHILE #i<=#count
BEGIN
SET #DATE =(select WeekDate from tablename where ID=#i)
update tablename set WeekNumber=(
SELECT DATEPART(WEEK, #DATE) -
DATEPART(WEEK, DATEADD(MM, DATEDIFF(MM,0,#DATE), 0))+ 1 AS WEEK_OF_MONTH)
where ID=#i
set #i=#i + 1
END;
it will update all your weeknumber field with corresponding number
Probably this helps you:
First you need to check the first of the day in your database
SELECT ##DATEFIRST
By default SUNDAY is first day of week (US). So you need to change it to 1 (Monday)
SET DATEFIRST 1
More inforamtion about SET DATEFIRST
In SQL Server by using DATEPART built-in function you can get the number of week in a year
SELECT DATAPART(WEEK, WeekDate)
Also you can get YEAR of your selected datetime
SELECT DATAPART(YEAR, WeekDate)
If you run these two queries for your first row (Let's say Week number 1)
SELECT DATEPART(WEEK, '2012-03-01 00:00:00.000') -- Output = 10
SELECT DATEPART(YEAR, '2012-03-01 00:00:00.000') -- Output = 2012
But this week should be your week number 1.
So you can easily subtract 2012 from your YEAR then multiply it by 52 (because we have 52 weeks in a year)
Substract 9 from your WEEKNUMBER
Add the numbers you get from above
(YEAR - 2012) * 52 + (WEEK - 9)
So by running this you can get the actual result
SELECT (DATEPART(YEAR, WeekDate) - 2012) * 52 + DATEPART(WEEK, WeekDate) - 9 AS WeekNumber
FROM yourTable