Calculate business days between two dates - sql

I tried the following query I got from an earlier question:
SELECT OrderNumber, InstallDate, CompleteDate,
(TRUNC(CompleteDate) - TRUNC(InstallDate) ) +1 -
((((TRUNC(CompleteDate,'D'))-(TRUNC(InstallDate,'D')))/7)*2) -
(CASE WHEN TO_CHAR(InstallDate,'DY','nls_date_language=english')='SUN' THEN 1 ELSE 0 END) -
(CASE WHEN TO_CHAR(CompleteDate,'DY','nls_date_language=english')='SAT' THEN 1 ELSE 0 END) as BusinessDays
FROM Orders
ORDER BY OrderNumber;
But I get an 'ORA-01722 - Invalid Number' error.
What am I doing wrong?
Following is my modified code that I'm having issues with:
select
CASE WHEN a.reqdt=0 THEN to_char('01/01/2010') ELSE TO_CHAR(TO_DATE('01-01-1970','DD-MM-YY') + ( a.reqdt/ 86400000 ), 'MM/DD/YYYY') END AS DT_SENT_TO_VENDOR,
CASE WHEN a.completedt=0 THEN to_char('01/01/2010') ELSE TO_CHAR(TO_DATE('01-01-1970','DD-MM-YY') + ( a.completedt/ 86400000 ), 'MM/DD/YYYY') END AS COMPLETED_DT,
(CASE WHEN a.completedt=0 THEN to_char('01/01/2010') ELSE TO_CHAR(TO_DATE('01-01-1970','DD-MM-YY') + ( a.completedt/ 86400000 ), 'dd-mm-yyyyY') END -
CASE WHEN a.reqdt=0 THEN to_char('01/01/2010') ELSE TO_CHAR(TO_DATE('01-01-1970','DD-MM-YY') + ( a.reqdt/ 86400000 ), 'MM/DD/YYYY') END ) + 1 -
/*(a.completedt - a.reqdt ) + 1 - */
((((TRUNC(a.completedt,'D'))) - (TRUNC(a.reqdt,'D'))/7)*2) -
(CASE WHEN TO_CHAR(a.reqdt,'DY','nls_date_language=american')='SUN' THEN 1 ELSE 0 END) -
(CASE WHEN TO_CHAR(a.completedt,'DY','nls_date_language=american')='SAT' THEN 1 ELSE 0 END) as BusinessDays
from EST_VER a;

Related

Inconsistent results with CTE (Recursion)

I am pulling my hair with this one!
I have a Stored Procedure that runs everyday:
-- DECLARING DATE VARIABLES
DECLARE #FirstDay date
-- SETTING UP INITIAL VALUES TO DATE VARIABLES
SET #FirstDay = (SELECT MIN(WK_Start) AS FirstDay FROM [TML_RDB].[COMPANY].[COMPANY_CALENDAR]);
-- CREATE DATE RANGE FROM #FIRST DAY
WITH DateRange AS (
SELECT #FirstDay AS [Date]
UNION ALL
SELECT DATEADD("dd",1,[Date]) FROM DateRange
WHERE [Date] < DATEADD("dd",-1,DATEFROMPARTS(YEAR(GETDATE())+2,3,1))
)
SELECT CAST(CONCAT(YEAR(DR.[Date]),FORMAT(MONTH(DR.[Date]),'00'),FORMAT(DAY(DR.[Date]),'00')) AS int) AS [DateKey]
,DR.[Date]
,DATENAME(DW,DR.[Date]) AS [DayOfWeekName]
,CONCAT(RIGHT(YEAR(DR.[Date]),2), FORMAT(DATEPART(WK, DATEADD("dd",-1,DR.[Date])),'00')) AS [CalendarWeek]
,CONCAT('W', RIGHT(YEAR(DR.[Date]),2), FORMAT(DATEPART(WK, DATEADD("dd",-1,DR.[Date])), '00')) AS [CalendarWeekName]
,(DATEPART(DW, DR.[Date])+5) % 7 + 1 AS [DayOfCalendarWeek]
--,DATEPART(WK, DATEADD("dd",-1,DR.[Date])) AS [CalendarWeek]
,MONTH(DR.[Date]) AS [CalendarMonth]
,DATENAME(MM, DR.[Date]) AS [CalendarMonthName]
,DATEPART(DD,DR.[Date]) AS [DayOfCalendarMonth]
,DATEPART(QQ,DR.[Date]) AS [CalendarQuarter]
,CONCAT('Q', DATEPART(QQ,DR.[Date])) AS [CalendarQuarterName]
,ROW_NUMBER() OVER (PARTITION BY YEAR(DR.[Date]), DATEPART(QQ,DR.[Date]) ORDER BY DR.[Date]) AS [DayOfCalendarQuarter]
,CASE
WHEN MONTH(DR.[Date]) < 7 THEN 1
ELSE 2
END AS [CalendarHalf]
,CASE
WHEN MONTH(DR.[Date]) < 7 THEN CONCAT('H',1)
ELSE CONCAT('H',2)
END AS [CalendarHalfName]
,CASE
WHEN YEAR(DR.[Date]) = 2009
THEN ROW_NUMBER() OVER (PARTITION BY YEAR(DR.[Date]), CASE WHEN MONTH(DR.[Date]) < 7 THEN 1 ELSE 2 END ORDER BY YEAR(DR.[Date]), CASE WHEN MONTH(DR.[Date]) < 7 THEN 1 ELSE 2 END) + DATEDIFF(DD,DATEFROMPARTS(YEAR(DR.[Date]),1,1),DATEFROMPARTS(YEAR(DR.[Date]),3,1))
ELSE ROW_NUMBER() OVER (PARTITION BY YEAR(DR.[Date]), CASE WHEN MONTH(DR.[Date]) < 7 THEN 1 ELSE 2 END ORDER BY YEAR(DR.[Date]), CASE WHEN MONTH(DR.[Date]) < 7 THEN 1 ELSE 2 END)
END AS [DayOfCalendarHalf]
,YEAR(DR.[Date]) AS [CalendarYear]
,CONCAT('Y', YEAR(DR.[Date])) AS [CalendarYearName]
,CASE
WHEN YEAR(DR.[Date]) = 2009
THEN ROW_NUMBER() OVER (PARTITION BY YEAR(DR.[Date]) ORDER BY DR.[Date]) + DATEDIFF(DD,DATEFROMPARTS(YEAR(DR.[Date]),1,1),DATEFROMPARTS(YEAR(DR.[Date]),3,1))
ELSE ROW_NUMBER() OVER (PARTITION BY YEAR(DR.[Date]) ORDER BY DR.[Date])
END AS [DayOfCalendarYear]
,CC.[WK_Code] AS [FiscalWeek]
,'W' + CC.[WK_Code] AS [FiscalWeekName]
,DATEPART(DW,DR.[Date]) AS [DayOfFiscalWeek]
,CC.[Sun_Period] AS [FiscalPeriod]
,'P' + CC.[Sun_Period] AS [FiscalPeriodName]
,ROW_NUMBER() OVER (PARTITION BY CC.[Sun_Period] ORDER BY CC.[Sun_Period]) AS [DayOfFiscalPeriod]
,CONCAT(LEFT(CC.[Sun_Period],2), FORMAT(CEILING(((CAST(Right(CC.[Sun_Period],2) AS int)) - 1)/3 ) + 1,'00')) AS [FiscalQuater]
,CONCAT('Q', LEFT(CC.[Sun_Period],2), FORMAT(CEILING(((CAST(Right(CC.[Sun_Period],2) AS int)) - 1)/3 ) + 1,'00')) AS [FiscalQuaterName]
,ROW_NUMBER() OVER (PARTITION BY CONCAT(LEFT(CC.[Sun_Period],2), FORMAT(CEILING(((CAST(Right(CC.[Sun_Period],2) AS int)) - 1)/3 ) + 1,'00')) ORDER BY CONCAT(LEFT(CC.[Sun_Period],2), FORMAT(CEILING(((CAST(Right(CC.[Sun_Period],2) AS int)) - 1)/3 ) + 1,'00'))) AS [DayOfFiscalQuarter]
,CONCAT(LEFT(CC.[Sun_Period],2), FORMAT(CEILING(((CAST(Right(CC.[Sun_Period],2) AS int)) - 1)/6 ) + 1,'00')) AS [FiscalHalf]
,CONCAT('H', LEFT(CC.[Sun_Period],2), FORMAT(CEILING(((CAST(Right(CC.[Sun_Period],2) AS int)) - 1)/6 ) + 1,'00')) AS [FiscalHalfName]
,ROW_NUMBER() OVER (PARTITION BY CONCAT(LEFT(CC.[Sun_Period],2), FORMAT(CEILING(((CAST(Right(CC.[Sun_Period],2) AS int)) - 1)/6 ) + 1,'00')) ORDER BY CONCAT(LEFT(CC.[Sun_Period],2), FORMAT(CEILING(((CAST(Right(CC.[Sun_Period],2) AS int)) - 1)/6 ) + 1,'00'))) AS [DayOfFiscalHalf]
,CONCAT(LEFT(YEAR(DR.[Date]),2), LEFT(CC.[Sun_Period],2)) AS [FiscalYear]
,CONCAT('Y', LEFT(YEAR(DR.[Date]),2), LEFT(CC.[Sun_Period],2)) AS [FiscalYearName]
,ROW_NUMBER() OVER (PARTITION BY CONCAT(LEFT(YEAR(DR.[Date]),2), LEFT(CC.[Sun_Period],2)) ORDER BY CONCAT(LEFT(YEAR(DR.[Date]),2), LEFT(CC.[Sun_Period],2))) AS [DayOfFiscalYear]
FROM DateRange DR
INNER JOIN [TML_RDB].[COMPANY].[COMPANY_CALENDAR] CC
ON DR.[Date] >= CC.[WK_Start] AND DR.[Date] <= CC.[WK_End]
OPTION (MAXRECURSION 10000)
When the above query is run using the Stored Procedure, i get the an output which is incorrect:
This count should start again from 1, not 217.
Now, what is weird is when i run this query manually i get the below result which is correct:
Some important infomration:
This query on some occasions returns the correct results, other times it does not.
The correct result is returned why i reduce the number of rows (Years)
This is to do with the Recursion but cannot undertand it fully.
Any assistance would be much appreciated.
Thanks,

How to do the Calculation by using Date format in Oracle SQL

Appreciate your help for the below question, i have struggle for a long time for this question. Please look at the example below.
(SELECT MIN(CASE WHEN SI.DATE_STAT >= 78000000000000000 AND
SUBSTR(DIGITS(SI.DATE_STAT),5,2) BETWEEN '01' AND '12' AND
SUBSTR(DIGITS(SI.DATE_STAT),9,1) BETWEEN '0' AND '3' AND
INT(SUBSTR(DIGITS(SI.DATE_STAT),7,2)) BETWEEN 1 AND
DAY(DATE(CAST(19+INT(SI.DATE_STAT / 100000000000000000) AS CHAR(2)) ||
TRANSLATE('YE-MN-01', DIGITS(SI.DATE_STAT), 'xxYEMNDA')) + 1 MONTH - 1 DAY)
THEN TIMESTAMP(CAST(19+INT(SI.DATE_STAT / 100000000000000000) AS CHAR(2)) ||
TRANSLATE('YE-MN-DA HR:UT:SC', DIGITS(SI.DATE_STAT),'xxYEMNDAxHRUTSC')) -
INT(MOD(3 - INT(SUBSTR(DIGITS(SI.DATE_STAT),9,1)),3)) DAYS +
INT(MOD(INT(SUBSTR(DIGITS(SI.DATE_STAT),16,2)) - 1,25) + 1) HOURS +
INT(MOD(4 - ((INT(SUBSTR(DIGITS(SI.DATE_STAT),16,2)) - 1) / 25),4) * 15)
MINUTES ELSE CAST(NULL AS TIMESTAMP)END)
FROM EXPORT.STAT_ITEM SI
WHERE (SI.INVOICE_REF = SH.SHPMNT_REF) AND SI.STAT_CODE = 'ABC') AS ABC,
(SELECT MIN(CASE WHEN SI.DATE_STAT >= 78000000000000000 AND
SUBSTR(DIGITS(SI.DATE_STAT),5,2) BETWEEN '01' AND '12' AND
SUBSTR(DIGITS(SI.DATE_STAT),9,1) BETWEEN '0' AND '3' AND
INT(SUBSTR(DIGITS(SI.DATE_STAT),7,2)) BETWEEN 1 AND
DAY(DATE(CAST(19+INT(SI.DATE_STAT / 100000000000000000) AS CHAR(2)) ||
TRANSLATE('YE-MN-01', DIGITS(SI.DATE_STAT), 'xxYEMNDA')) + 1 MONTH - 1 DAY)
THEN TIMESTAMP(CAST(19+INT(SI.DATE_STAT / 100000000000000000) AS CHAR(2)) ||
TRANSLATE('YE-MN-DA HR:UT:SC', DIGITS(SI.DATE_STAT),'xxYEMNDAxHRUTSC')) -
INT(MOD(3 - INT(SUBSTR(DIGITS(SI.DATE_STAT),9,1)),3)) DAYS +
INT(MOD(INT(SUBSTR(DIGITS(SI.DATE_STAT),16,2)) - 1,25) + 1) HOURS +
INT(MOD(4 - ((INT(SUBSTR(DIGITS(SI.DATE_STAT),16,2)) - 1) / 25),4) * 15)
MINUTES ELSE CAST(NULL AS TIMESTAMP)END)
FROM EXPORT.STAT_ITEM SI
WHERE (SI.INVOICE_REF = SH.SHPMNT_REF) AND SI.STAT_CODE = 'DEF') AS DEF,
//This should be wrong and I'm getting error.
coalesce((days(DEF) - days(ABC)),'0') as TotalTransitTime
What I wan is to show the date betweeen "DEF" and "ABC" and the default will be 0 if DEF or ABC is missing. Please help. Thanks a lot!

Getting an error day of month must be between 1 and last day of month

HiAll,
i am getting an error
ORA-01847: day of month must be between 1 and last day of month
01847. 00000 - "day of month must be between 1 and last day of month"
please suggest on this, below is sample i used in my query
when ((
(( x.DailyKMUsage * (trunc(x.std)-trunc(x.ced)) ))
/ case when x.ckm <= 0 then 1 else x.ckm end
)*100 ) > 0
then (((
(( x.DailyKMUsage * (trunc(x.std)-trunc(x.ced)) ))
/ case when x.ckm <= 0 then 1 else x.ckm end
)*100 )|| '% Over Utilised')
when ((
(( x.DailyKMUsage * (trunc(x.std)-trunc(x.ced)) ))
/ case when x.ckm <= 0 then 1 else x.ckm end
)*100 ) < 0
then (((
(( x.DailyKMUsage * (trunc(x.std)-trunc(x.ced)) ))
/ case when x.ckm <= 0 then 1 else x.ckm end
)*100 )|| '% Under Utilised')

Sorting data by YEAR

I am completely new to SQL and have really only run statements with minimal modifications. I am currently trying to modify this specific query:
SELECT DISTINCT (ROUND (windspeed * 2, -1) / 2) AS wndspd,
SUM (CASE WHEN month = 1 THEN 1 ELSE NULL END) AS January,
SUM (CASE WHEN month = 2 THEN 1 ELSE NULL END) AS February,
SUM (CASE WHEN month = 3 THEN 1 ELSE NULL END) AS March,
SUM (CASE WHEN month = 4 THEN 1 ELSE NULL END) AS April,
SUM (CASE WHEN month = 5 THEN 1 ELSE NULL END) AS May,
SUM (CASE WHEN month = 6 THEN 1 ELSE NULL END) AS June,
SUM (CASE WHEN month = 7 THEN 1 ELSE NULL END) AS July,
SUM (CASE WHEN month = 8 THEN 1 ELSE NULL END) AS August,
SUM (CASE WHEN month = 9 THEN 1 ELSE NULL END) AS September,
SUM (CASE WHEN month = 10 THEN 1 ELSE NULL END) AS October,
SUM (CASE WHEN month = 11 THEN 1 ELSE NULL END) AS November,
SUM (CASE WHEN month = 12 THEN 1 ELSE NULL END) AS December
FROM table1
WHERE platformid = 'coollocation'
AND networktype = 'typeofcoollocation'
AND (windspeedqc <> '2' OR windspeedqc IS NULL)
GROUP BY ROUND (windspeed * 2, -1) / 2
ORDER BY ROUND (windspeed * 2, -1) / 2;
What I want from the query is to instead of sorting by months, sort by all the years that are available for the specific location (platformid). So far I have just modified the script so that it looks like this:
SELECT DISTINCT
(ROUND (windspeed * 2, -1) / 2) AS wndspd,
SUM (
CASE
WHEN TO_CHAR (observationtime, 'YYYY') = 1957 THEN 1
ELSE NULL
END)
AS given_year,
SUM (
CASE
WHEN TO_CHAR (observationtime, 'YYYY') = 1958 THEN 1
ELSE NULL
END)
AS GIVEN_YEAR2
FROM table1
WHERE platformid = 'coollocation'
AND networktype = 'typeofcoollocation'
AND (windspeedqc <> '2' OR windspeedqc IS NULL)
GROUP BY ROUND (windspeed * 2, -1) / 2
ORDER BY ROUND (windspeed * 2, -1) / 2;
The problem is that I know that the years go from 1957-2015. I'm pretty sure that there is a more efficient way to list out the information that I want without creating a specific SUM string for every single year. I have no idea how to do that however. Please help!
You can try creating a PIVOT query
SELECT wndspd, [1957], [1958], [1959],...etc....[2013], [2014], [2015] FROM
(
SELECT (ROUND (windspeed * 2, -1) / 2) AS wndspd,
YEAR(observationtime) yr
FROM table1
WHERE platformid = 'coollocation'
AND networktype = 'typeofcoollocation'
AND (windspeedqc <> '2' OR windspeedqc IS NULL)
) src
PIVOT (
COUNT(yr)
FOR yr IN ([1957],[1958], [1959],...etc....[2013], [2014], [2015])
) pvt
you'll have to fill in all of the other years between 1959 and 2013.
here's an easier way to create all of the columns from 1957 to the current year.
DECLARE #PivotCols VARCHAR(MAX),
#MinYear INT = 1957,
#CurYear INT = YEAR(GETDATE())
WHILE #MinYear < #CurYear
BEGIN
SET #PivotCols = COALESCE( #PivotCols + '],[', '[') + CONVERT(VARCHAR, #MinYear)
SET #MinYear = #MinYear + 1
END
SET #PivotCols = CONCAT(#PivotCols,'],[',CONVERT(VARCHAR, #MinYear),']')
DECLARE #Sql VARCHAR(MAX) = '
SELECT wndspd, ' + #PivotCols + ' FROM
(
SELECT (ROUND (windspeed * 2, -1) / 2) AS wndspd,
YEAR(observationtime) yr
FROM table1
WHERE platformid = ''coollocation''
AND networktype = ''typeofcoollocation''
AND (windspeedqc <> ''2'' OR windspeedqc IS NULL)
) src
PIVOT (
COUNT(yr)
FOR yr IN (' + #PivotCols + ')
) pvt
'
EXEC (#Sql)
I think you are essentially trying to do this:
SELECT DISTINCT (ROUND (windspeed * 2, -1) / 2) AS wndspd
,TO_CHAR(observationtime, 'YYYY') as year,
,COUNT(1) as occurrences
FROM table1
WHERE platformid = 'coollocation'
AND networktype = 'typeofcoollocation'
AND (windspeedqc <> '2' OR windspeedqc IS NULL)
GROUP BY (ROUND(windspeed * 2, -1) / 2), TO_CHAR(observationtime, 'YYYY')
ORDER BY 1, 2;
...however the count of occurrences in each year would then be represented by a row instead of a column.
Unfortunately there is no easy way to pivot the rows in this query into columns because you fundamentally need to know how many columns there are and ensure each row has the values populated properly.
At the end of the day you'll need to add a line for each year to your SELECT clause. It could look like this:
SELECT yearly.wndspd
,SUM(CASE WHEN yearly.year='1957' THEN yearly.occurrences ELSE 0 END) as 1957
,SUM(CASE WHEN yearly.year='1958' THEN yearly.occurrences ELSE 0 END) as 1958
...
,SUM(CASE WHEN yearly.year='2015' THEN yearly.occurrences ELSE 0 END) as 2015
FROM
(SELECT DISTINCT (ROUND (windspeed * 2, -1) / 2) AS wndspd
,TO_CHAR(observationtime, 'YYYY') as year,
,COUNT(1) as occurrences
FROM table1
WHERE platformid = 'coollocation'
AND networktype = 'typeofcoollocation'
AND (windspeedqc <> '2' OR windspeedqc IS NULL)
GROUP BY (ROUND(windspeed * 2, -1) / 2), TO_CHAR(observationtime, 'YYYY')) yearly
GROUP BY yearly.wndspd
ORDER BY 1, 2;

error in sql query

I have this query:
( SELECT
SUM(
CONVERT(
FLOAT,
CASE '01'
WHEN '01' THEN
CASE SIGN((sltr_tran_amt - ISNULL(sltr_matched_amt, 0)))
WHEN 1 THEN
CASE DBO.glas_aging_oth(CONVERT(DATETIME, '2009/04/04') - FLOOR(sltr_pstng_date))
WHEN 0 THEN (sltr_tran_amt - ISNULL(sltr_matched_amt, 0))
ELSE 0
END
ELSE 0
END
WHEN '02' THEN
CASE SIGN((sltr_tran_amt - ISNULL(sltr_matched_amt, 0)))
WHEN -1 THEN
CASE DBO.glas_aging_oth(CONVERT(DATETIME, '2009/04/04') - FLOOR(sltr_doc_date))
WHEN 0 THEN (sltr_tran_amt - ISNULL(sltr_matched_amt, 0))
ELSE 0
END
ELSE 0
END
END
)
)
FROM
WHERE
CASE '01'
WHEN '01' THEN sltr_pstng_date
ELSE sltr_doc_date
END =
CASE '01'
WHEN '01' THEN sltr_pstng_date
ELSE sltr_doc_date
END
) thirty_days,
from glas_sl_transactions
When i execute this query, an error is ocurring near 'where'. How do I avoid this? If possible, please also tell me how to shorten this query.
Somewhere deep in the middle of that query, you have FROM WHERE - ie. you are missing a table name after the FROM.
Also, you can make it shorter by removing all the CASE '1' WHEN '1' THEN bits, since '1' is always '1'.
Edit: Ok, here's my reformatting of it:
( SELECT
SUM(
CONVERT(
FLOAT,
CASE '01'
WHEN '01' THEN
CASE SIGN((sltr_tran_amt - ISNULL(sltr_matched_amt, 0)))
WHEN 1 THEN
CASE DBO.glas_aging_oth(CONVERT(DATETIME, '2009/04/04') - FLOOR(sltr_pstng_date))
WHEN 0 THEN (sltr_tran_amt - ISNULL(sltr_matched_amt, 0))
ELSE 0
END
ELSE 0
END
WHEN '02' THEN
CASE SIGN((sltr_tran_amt - ISNULL(sltr_matched_amt, 0)))
WHEN -1 THEN
CASE DBO.glas_aging_oth(CONVERT(DATETIME, '2009/04/04') - FLOOR(sltr_doc_date))
WHEN 0 THEN (sltr_tran_amt - ISNULL(sltr_matched_amt, 0))
ELSE 0
END
ELSE 0
END
END
)
)
FROM
WHERE
CASE '01'
WHEN '01' THEN sltr_pstng_date
ELSE sltr_doc_date
END =
CASE '01'
WHEN '01' THEN sltr_pstng_date
ELSE sltr_doc_date
END
) thirty_days,
from glas_sl_transactions
So it looks like you are also missing an END in that gap before the first closing bracket above the FROM.
Also, it contains a lot of code that will never be executed. Eg.
CASE '01'
WHEN '01' /* always executed */
WHEN '02' /* never executed */
END
The where-clause also boils down to 1=1, and can therefore be removed.
In conclusion, here's what I think it should look like.
SELECT SUM( CONVERT(
FLOAT,
CASE SIGN((sltr_tran_amt - ISNULL(sltr_matched_amt, 0)))
WHEN 1 THEN
CASE DBO.glas_aging_oth(CONVERT(DATETIME, '2009/04/04') - FLOOR(sltr_pstng_date))
WHEN 0 THEN (sltr_tran_amt - ISNULL(sltr_matched_amt, 0))
ELSE 0
END
ELSE 0
END
))
from glas_sl_transactions