Simplyfing update query with case when - sql-server

I have a query where there is a lot of repetitions of one condition. I am wondering - is it possible to put this condition into variable or something like that, so not the whole sentence is repeated each time?
The part which is repeating:
ISNULL((CASE WHEN IS_HOLIDAY = 1 THEN 2.5 * NETO_HOUR
WHEN DAY_IN_WEEK = 'Sunday' THEN NETO_HOUR END),0)
In query it looks like this:
UPDATE #tblALL_HOURS SET REG_WORK_COST = (CASE WHEN MINUTE_FROM >= 0 AND MINUTE_FROM <= #6h AND MINUTE_TO >= #6h AND MINUTE_TO <= #18h
AND IS_ABSENT = 0
THEN (DATEDIFF(MINUTE, DATEADD(MINUTE, #6h, CAST(CAST(DATE_TO AS DATE) AS DATETIME)), date_to)/60.00) * (BRUTO_HOUR + ISNULL((CASE WHEN IS_HOLIDAY = 1 THEN 2.5 * NETO_HOUR WHEN DAY_IN_WEEK = 'Sunday' THEN NETO_HOUR END),0))
WHEN MINUTE_FROM >= 0 AND MINUTE_FROM <= #6h AND MINUTE_TO >= #18h AND MINUTE_TO < #24h
AND IS_ABSENT = 0
THEN 12.00 * (BRUTO_HOUR + ISNULL((CASE WHEN IS_HOLIDAY = 1 THEN 2.5 * NETO_HOUR WHEN DAY_IN_WEEK = 'Sunday' THEN NETO_HOUR END),0))
WHEN MINUTE_FROM >= #6h AND MINUTE_FROM <= #18h AND MINUTE_TO >= #6h AND MINUTE_TO <= #18h
AND IS_ABSENT = 0
THEN (DATEDIFF(MINUTE, DATE_FROM, DATE_TO) / 60.00) * (BRUTO_HOUR + ISNULL((CASE WHEN IS_HOLIDAY = 1 THEN 2.5 * NETO_HOUR WHEN DAY_IN_WEEK = 'Sunday' THEN NETO_HOUR END),0))
WHEN MINUTE_FROM >= #6h AND MINUTE_FROM <= #18h AND MINUTE_TO >= #18h AND MINUTE_TO < #24h
AND IS_ABSENT = 0
THEN (DATEDIFF(MINUTE, DATE_FROM, DATEADD(MINUTE, #18h, CAST(CAST(DATE_FROM AS DATE) AS DATETIME))) / 60.00) * (BRUTO_HOUR + ISNULL((CASE WHEN IS_HOLIDAY = 1 THEN 2.5 * NETO_HOUR WHEN DAY_IN_WEEK = 'Sunday' THEN NETO_HOUR END),0))
END)
Is it possible to have something like this instead:
WHEN MINUTE_FROM >= #6h AND MINUTE_FROM <= #18h AND MINUTE_TO >= #18h AND MINUTE_TO < #24h AND IS_ABSENT = 0 THEN (DATEDIFF(MINUTE, DATE_FROM, DATEADD(MINUTE, #18h, CAST(CAST(DATE_FROM AS DATE) AS DATETIME))) / 60.00) * (BRUTO_HOUR + #myCondition)

Use a simple CTE that returns all the columns of #tblALL_HOURS and the value returned by ISNULL function:
ISNULL(CASE WHEN IS_HOLIDAY = 1 THEN 2.5 * NETO_HOUR WHEN DAY_IN_WEEK = 'Sunday' THEN NETO_HOUR END,0)
as a column and then update With the CTE and use that column in place of the condition:
WITH cte AS (
SELECT *,
ISNULL(CASE WHEN IS_HOLIDAY = 1 THEN 2.5 * NETO_HOUR WHEN DAY_IN_WEEK = 'Sunday' THEN NETO_HOUR END,0) AS myCondition
FROM #tblALL_HOURS
)
UPDATE cte
SET REG_WORK_COST = CASE
WHEN MINUTE_FROM >= 0 AND MINUTE_FROM <= #6h AND MINUTE_TO >= #6h AND MINUTE_TO <= #18h AND IS_ABSENT = 0
THEN (DATEDIFF(MINUTE, DATEADD(MINUTE, #6h, CAST(CAST(DATE_TO AS DATE) AS DATETIME)), date_to)/60.00) * (BRUTO_HOUR + myCondition)
WHEN MINUTE_FROM >= 0 AND MINUTE_FROM <= #6h AND MINUTE_TO >= #18h AND MINUTE_TO < #24h AND IS_ABSENT = 0
THEN 12.00 * (BRUTO_HOUR + myCondition)
WHEN MINUTE_FROM >= #6h AND MINUTE_FROM <= #18h AND MINUTE_TO >= #6h AND MINUTE_TO <= #18h AND IS_ABSENT = 0
THEN (DATEDIFF(MINUTE, DATE_FROM, DATE_TO) / 60.00) * (BRUTO_HOUR + myCondition)
WHEN MINUTE_FROM >= #6h AND MINUTE_FROM <= #18h AND MINUTE_TO >= #18h AND MINUTE_TO < #24h AND IS_ABSENT = 0
THEN (DATEDIFF(MINUTE, DATE_FROM, DATEADD(MINUTE, #18h, CAST(CAST(DATE_FROM AS DATE) AS DATETIME))) / 60.00) * (BRUTO_HOUR + myCondition)
END

Related

Count Number of Saturdays in a date range - SQL

I have a report which looks for orders during a given date range... It returns the DateName from the report to give me mondays, it then gives me times from the report, to give me 859 for 08:59 for example.. I then use a case on this report to do the following...
WHEN (DATENAME(DW,T1.DocDate)) = 'Monday' AND T1.DocTime >= '700' AND T1.DocTime <= '859' THEN '1 Monday 07:00-08:59'
What I want to achieve, is the count for "1 Monday 07:00-08:59" to be divided by 2 if there has been 2 mondays, divided by 3 if there has been 3 mondays etc... but I have to be able to have it divide by 3 mondays for example, but 2 wednesdays if the date is a tuesday...
The report currently gives a Total of all orders placed in a datetime grouped together but has no division to average for each day.
SELECT (DATENAME(DW, T1.DocDate)) AS Weekday,
T1.DocTime AS Time,
SUM(T1.DocTotal) AS Value,
CASE
WHEN (DATENAME(DW, T1.DocDate)) = 'Monday'
AND T1.DocTime >= '700'
AND T1.DocTime <= '859' THEN '1 Monday 07:00-08:59'
FROM ORDR T1
INNER JOIN OCRD T0 ON T0.CardCode = T1.CardCode
WHERE (T1.DocDate >= #Start
AND T1.DocDate <= #End)
AND T0.QryGroup20 = 'Y'
AND T1.Canceled = 'N'
GROUP BY T1.DocTime,
T1.DocDate;
I expect the report to count the mondays / tuesdays etc that occur between #START and #END to give me an average sale per day and time.Then be able to then somehow divide by the count of the defined days in the case statement. (I'll hopefully be doing this part in Crystal Reports) but if i can get the first part, I'll work on the second half.
Just cross join the DW_Count subquery, which returns the count of every weekday in your orders range. Then you can count your avg for each weekday
SELECT (DATENAME(DW, T1.DocDate)) AS Weekday,
T1.DocTime AS Time,
SUM(T1.DocTotal) AS Value,
SUM(T1.DocTotal)/(CASE WHEN DATENAME(DW, T1.DocDate) = 'Monday' then DW_Count.MonCount
WHEN DATENAME(DW, T1.DocDate) = 'Tuesday' then DW_Count.TueCount
WHEN DATENAME(DW, T1.DocDate) = 'Wednesday' then DW_Count.WedCount
WHEN DATENAME(DW, T1.DocDate) = 'Thursday' then DW_Count.ThuCount
WHEN DATENAME(DW, T1.DocDate) = 'Friday' then DW_Count.FriCount
WHEN DATENAME(DW, T1.DocDate) = 'Saturday' then DW_Count.SatCount
WHEN DATENAME(DW, T1.DocDate) = 'Sunday' then DW_Count.SunCount) AS AvgValue
CASE
WHEN (DATENAME(DW, T1.DocDate)) = 'Monday'
AND T1.DocTime >= '700'
AND T1.DocTime <= '859' THEN '1 Monday 07:00-08:59'
FROM ORDR T1
INNER JOIN OCRD T0 ON T0.CardCode = T1.CardCode
CROSS JOIN (select sum(case when DATENAME(DW, DW_Count.DateValue) = 'Monday' then 1 else 0 end) as MonCount,
sum(case when DATENAME(DW, DW_Count.DateValue) = 'Tuesday' then 1 else 0 end) as TueCount,
sum(case when DATENAME(DW, DW_Count.DateValue) = 'Wednesday' then 1 else 0 end) as WedCount,
sum(case when DATENAME(DW, DW_Count.DateValue) = 'Thursday' then 1 else 0 end) as ThuCount,
sum(case when DATENAME(DW, DW_Count.DateValue) = 'Friday' then 1 else 0 end) as FriCount,
sum(case when DATENAME(DW, DW_Count.DateValue) = 'Saturday' then 1 else 0 end) as SatCount,
sum(case when DATENAME(DW, DW_Count.DateValue) = 'Sunday' then 1 else 0 end) as SunCount
from (select distinct DocDate from ORDR where (T1.DocDate >= #Start AND T1.DocDate <= #End))) AS DW_Count
WHERE (T1.DocDate >= #Start
AND T1.DocDate <= #End)
AND T0.QryGroup20 = 'Y'
AND T1.Canceled = 'N'
GROUP BY T1.DocTime,
T1.DocDate;
You can use the below logic-
For MSSQL
DECLARE #DT1 DATE = '20190802'
DECLARE #DT2 DATE = '20190820'
DECLARE #SatCount INT = 0
WHILE #DT1<= #DT2
BEGIN
SET #SatCount = #SatCount + CASE WHEN DATEPART(WeekDay,#DT1) = 7 THEN 1 ELSE 0 END
SET #DT1 = DATEADD(DD,1,#DT1)
END
SELECT #SatCount
Just one more option-
DECLARE #DT1 DATE = '20190802',
#DT2 DATE = '20190920';
SELECT SUM(CASE WHEN DATEPART(WeekDay,Date) = 7 THEN 1 ELSE 0 END)
FROM
(
SELECT TOP (DATEDIFF(DAY, #DT1, #DT2) + 1)
Date = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, #DT1)
FROM sys.all_objects a
-- A System table just used for creating multiple rows.
CROSS JOIN sys.all_objects b
-- CROSS JOIN will create number of row = original number of row X original number of row.
)A

Where condition a outer applied sql query

I am using a sql query but sorry to say unable to use a where condition. I post my query below.
SELECT * , CAST( RIGHT(FileNo,3) AS numeric) as IntFileNo
FROM ExportLcs A
OUTER APPLY (
SELECT SUM(ReceivedTTUsd) AS TtTotal,
SUM(ReceivedPDCUsd) AS PdcTotal,
SUM(CASE WHEN ReceivedPDCUsd > 0 THEN 1 ELSE 0 END) AS PdcCashCount,
SUM(CASE WHEN ReceivedPDCUsd > 0 THEN ConvertRate ELSE 0 END) AS PdcRateTotal,
SUM(CASE WHEN ConvertRate > 0 THEN CEILING(ReceivedPDCUsd / ConvertRate) ELSE 0 END) AS PdcTotalUsd,
Count(ExportLcId) AS TotalPaymentCount
FROM dbo.ExportPayments G
WHERE A.ExportLcId = G.ExportLcId AND (G.PdcTotal+G.PdcTotalUsd)>0
) AS G
I want to use condition like
A.ExportLcId = G.ExportLcId AND (G.PdcTotal+G.PdcTotalUsd)>0
but and part not working.
Any one can help.
How about having clause instead of where?
SELECT * , CAST(RIGHT(FileNo, 3) AS NUMERIC) AS IntFileNo
FROM dbo.ExportLcs AS A
OUTER APPLY (
SELECT SUM(ReceivedTTUsd) AS TtTotal
, SUM(ReceivedPDCUsd) AS PdcTotal
, SUM(CASE WHEN ReceivedPDCUsd > 0 THEN 1 ELSE 0 END) AS PdcCashCount
, SUM(CASE WHEN ReceivedPDCUsd > 0 THEN ConvertRate ELSE 0 END) AS PdcRateTotal
, SUM(CASE WHEN ConvertRate > 0 THEN CEILING(ReceivedPDCUsd / ConvertRate) ELSE 0 END) AS PdcTotalUsd
, COUNT(ExportLcId) AS TotalPaymentCount
FROM dbo.ExportPayments AS G
WHERE A.ExportLcId = G.ExportLcId
HAVING (SUM(ReceivedPDCUsd) + SUM(CASE WHEN ConvertRate > 0 THEN CEILING(ReceivedPDCUsd / ConvertRate) ELSE 0 END)) > 0
) AS G;
You should consider using Outer Join instead, so try the following:
SELECT * , CAST( RIGHT(FileNo,3) AS numeric) as IntFileNo from ExportLcs A left outer join
(
SELECT SUM(ReceivedTTUsd) AS TtTotal,
SUM(ReceivedPDCUsd) AS PdcTotal,
SUM(CASE WHEN ReceivedPDCUsd > 0 THEN 1 ELSE 0 END) AS PdcCashCount,
SUM(CASE WHEN ReceivedPDCUsd > 0 THEN ConvertRate ELSE 0 END) AS PdcRateTotal,
SUM(CASE WHEN ConvertRate > 0 THEN CEILING(ReceivedPDCUsd / ConvertRate) ELSE 0 END) AS PdcTotalUsd,
Count(ExportLcId) AS TotalPaymentCount
FROM dbo.ExportPayments) G
on A.ExportLcId = G.ExportLcId where (G.PdcTotal+G.PdcTotalUsd)>0
just put your part where clause outside.
SELECT * , CAST( RIGHT(FileNo,3) AS numeric) as IntFileNo
FROM Export
where (G.PdcTotal+G.PdcTotalUsd)>0Lcs A
OUTER APPLY (
SELECT SUM(ReceivedTTUsd) AS TtTotal,
SUM(ReceivedPDCUsd) AS PdcTotal,
SUM(CASE WHEN ReceivedPDCUsd > 0 THEN 1 ELSE 0 END) AS PdcCashCount,
SUM(CASE WHEN ReceivedPDCUsd > 0 THEN ConvertRate ELSE 0 END) AS PdcRateTotal,
SUM(CASE WHEN ConvertRate > 0 THEN CEILING(ReceivedPDCUsd / ConvertRate) ELSE 0 END) AS PdcTotalUsd,
Count(ExportLcId) AS TotalPaymentCount
FROM dbo.ExportPayments G
WHERE A.ExportLcId = G.ExportLcId
) AS G

SQL - AVG call rate by time of day and day of week

I have a table with records for each telephone call.
I want to create a matrix where I have the average call rate per 30 minute time segment over the day by day of week. Each call has a start time which is a date/time
i.e.
I want to display Mon-Sun as row headers and 30 min intervals as column headers. The content is the average count of calls for each day (Mon - Sun) in each particular 30 minute segment. This is where I have got but it isn't what I want. It sums the number of calls by time segment and I cant work out how to get averages.
I hope some can point me in the right direction -
SQL is not something I use often so be gentle :-)
set dateformat dmy
SET DATEFIRST 1 -- Start with Monday
SELECT datepart(dw,starttime) as 'Day',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) <= 30) THEN 1 ELSE 0 END) AS 'Midnight-12:30am',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) > 30) THEN 1 ELSE 0 END) AS '12:30am-1am',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) <= 30) THEN 1 ELSE 0 END) AS '1am-1:30am',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) > 30) THEN 1 ELSE 0 END) AS '1:30am-2am',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) <= 30) THEN 1 ELSE 0 END) AS '2am-2:30am',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) > 30) THEN 1 ELSE 0 END) AS '2:30am-3am',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) <= 30) THEN 1 ELSE 0 END) AS '3am-3:30am',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) > 30) THEN 1 ELSE 0 END) AS '3:30am-4am',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) <= 30) THEN 1 ELSE 0 END) AS '4am-4:30am',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) > 30) THEN 1 ELSE 0 END) AS '4:30am-5am',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) <= 30) THEN 1 ELSE 0 END) AS '5am-5:30am',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) > 30) THEN 1 ELSE 0 END) AS '5:30am-6am',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) <= 30) THEN 1 ELSE 0 END) AS '6am-6:30am',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) > 30) THEN 1 ELSE 0 END) AS '6:30am-7am',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) <= 30) THEN 1 ELSE 0 END) AS '7am-7:30am',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) > 30) THEN 1 ELSE 0 END) AS '7:30am-8am',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) > 30) THEN 1 ELSE 0 END) AS '8:30am-9am',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) <= 30) THEN 1 ELSE 0 END) AS '9am-9:30am',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) > 30) THEN 1 ELSE 0 END) AS '10:30am-11am',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) <= 30) THEN 1 ELSE 0 END) AS '11am-11:30am',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) > 30) THEN 1 ELSE 0 END) AS '11:30am-Noon',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) <= 30) THEN 1 ELSE 0 END) AS 'Noon-12:30pm',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) > 30) THEN 1 ELSE 0 END) AS '1pm-1:30pm',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) <= 30) THEN 1 ELSE 0 END) AS '1:30pm-2pm',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) > 30) THEN 1 ELSE 0 END) AS '2pm-2:30pm',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) <= 30) THEN 1 ELSE 0 END) AS '2:30pm-3pm',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) > 30) THEN 1 ELSE 0 END) AS '3pm-3:30pm',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) <= 30) THEN 1 ELSE 0 END) AS '4:30pm-4pm',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) > 30) THEN 1 ELSE 0 END) AS '4pm-5:30pm',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) <= 30) THEN 1 ELSE 0 END) AS '5:30pm-6pm',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) > 30) THEN 1 ELSE 0 END) AS '6pm-6:30pm',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) <= 30) THEN 1 ELSE 0 END) AS '6:30pm-7pm',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) > 30) THEN 1 ELSE 0 END) AS '7pm-7:30pm',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) <= 30) THEN 1 ELSE 0 END) AS '7:30pm-8pm',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) > 30) THEN 1 ELSE 0 END) AS '8pm-8:30pm',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) <= 30) THEN 1 ELSE 0 END) AS '8:30pm-9pm',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) > 30) THEN 1 ELSE 0 END) AS '9pm-9:30pm',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) <= 30) THEN 1 ELSE 0 END) AS '9:30pm-10pm',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) > 30) THEN 1 ELSE 0 END) AS '10pm-10:30pm',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) <= 30) THEN 1 ELSE 0 END) AS '10:30pm-11pm',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) > 30) THEN 1 ELSE 0 END) AS '11pm-11:30pm',
SUM(CASE WHEN (DATEPART(hour,StartTime) = 7 and DATEPART(Minute,StartTime) <= 30) THEN 1 ELSE 0 END) AS '11:30pm-Midnight'
FROM [dbo].[CallList]
where StartTime>'1/6/2015'
and StartTime<'30/6/2015'
GROUP BY datepart(dw,starttime)
ORDER BY datepart(dw,starttime)
Creating a WHILE loop to insert into a temp table then doing the aggregation after the fact is a viable option. See below:
CREATE TABLE #Data
(
ID UNIQUEIDENTIFIER
,DateIn DATETIME
)
INSERT INTO #Data
VALUES
(NEWID(), '2016-05-17 00:01:00'),
(NEWID(), '2016-05-17 00:21:00'),
(NEWID(), '2016-05-17 01:01:00'),
(NEWID(), '2016-05-17 05:41:00'),
(NEWID(), '2016-05-17 06:51:00'),
(NEWID(), '2016-05-17 13:21:00'),
(NEWID(), '2016-05-17 18:01:00'),
(NEWID(), '2016-05-17 21:11:00'),
(NEWID(), '2016-05-17 23:41:00'),
(NEWID(), '2016-05-17 23:51:00')
DECLARE #Start DATETIME
DECLARE #End DATETIME
SET #Start = '2016-05-17 00:00:00'
SET #End = '2016-05-17 00:30:00'
CREATE TABLE #Temp
(
ID UNIQUEIDENTIFIER
,[Time Increment] VARCHAR(100)
)
WHILE #End <= '2016-05-17 23:30:00'
BEGIN
INSERT INTO #Temp
SELECT
ID
,CAST(#Start AS VARCHAR) + ' - ' + CAST(#End AS VARCHAR) [Time Increment]
FROM #Data
WHERE DateIn >= #Start
AND DateIn < #End
SET #Start = DATEADD(Minute, 30, #Start)
SET #End = DATEADD(Minute, 30, #End)
END
SELECT
[Time Increment]
,COUNT(ID) [Count]
FROM #Temp
GROUP BY [Time Increment]
DROP TABLE #Temp
DROP TABLE #Data
In this example, the result is the following:
Time Increment |Count
May 17 2016 1:00AM - May 17 2016 1:30AM | 1
May 17 2016 1:00PM - May 17 2016 1:30PM | 1
May 17 2016 5:30AM - May 17 2016 6:00AM | 1
May 17 2016 6:00PM - May 17 2016 6:30PM | 1
May 17 2016 6:30AM - May 17 2016 7:00AM | 1
May 17 2016 9:00PM - May 17 2016 9:30PM | 1
May 17 2016 12:00AM - May 17 2016 12:30AM | 2

SQL - Getting working days of date range within another date range

I have 2 Sets for Date Ranges :
#StartDate and #EndDate : Being passed to a stored procedure
ProjectStartDate and ProjectEndDate : In the Database
The goal is to get the number of working days (public holidays are ignored) that ProjectStartDate and ProjectEndDate fall between #StartDate and #EndDate.
Example 1:
#StartDate = 2016/03/21
#EndDate = 2016/03/25
ProjectStartDate = 2016/03/13
ProjectEndDate = 2016/03/22
So the number of working days I need to work out are where ProjectStartDate and ProjectEndDate fall beween #StartDate and #Endate - in this case, number of working days would be 2(Mon - Fri)
Example 2 :
ProjectStartDate = 2016/03/22
ProjectEndDate = 2016/03/29
So the number of working days I need to work out are where ProjectStartDate and ProjectEndDate fall between #StartDate and #Endate - in this case, number of working days would be 4(Mon - Fri)
Example 3 :
ProjectStartDate = 2016/03/13
ProjectEndDate = 2016/03/29
So the number of working days I need to work out are where ProjectStartDate and ProjectEndDate fall between #StartDate and #Endate - in this case, number of working days would be 5(Mon - Fri)
The code I have to work out the working days is as follows :
(DATEDIFF(dd, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart), ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd)) + 1)
-(DATEDIFF(wk, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart), ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd)) * 2)
-(CASE WHEN DATENAME(dw, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart)) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart)) = 'Saturday' THEN 1 ELSE 0 END)
I have tried to get the result, but it partially works. I know there is a simpler way of doing this :
CASE WHEN(CASE WHEN #StartDate <= ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart)
THEN (DATEDIFF(dd, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart), #EndDate) + 1)
-(DATEDIFF(wk, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart), #EndDate) * 2)
-(CASE WHEN DATENAME(dw, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart)) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart)) = 'Saturday' THEN 1 ELSE 0 END)
ELSE (DATEDIFF(dd, #StartDate, ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd)) + 1)
-(DATEDIFF(wk, #StartDate, ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd)) * 2)
-(CASE WHEN DATENAME(dw, #StartDate) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, #StartDate) = 'Saturday' THEN 1 ELSE 0 END) END) >= 5
THEN 5
ELSE (CASE WHEN #StartDate <= ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart)
THEN (DATEDIFF(dd, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart), #EndDate) + 1)
-(DATEDIFF(wk, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart), #EndDate) * 2)
-(CASE WHEN DATENAME(dw, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart)) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart)) = 'Saturday' THEN 1 ELSE 0 END)
ELSE (DATEDIFF(dd, #StartDate, ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd)) + 1)
-(DATEDIFF(wk, #StartDate, ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd)) * 2)
-(CASE WHEN DATENAME(dw, #StartDate) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, #StartDate) = 'Saturday' THEN 1 ELSE 0 END) END) END AS DaysCalculated
So I ended up finding the answer, it seems. I would prefer to find a cleaner, neater way... but I cant spend more time on this and this works for now. If Anyone has a cleaner, neater option, please let me know. Thanks.
(CASE WHEN ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart) >= #StartDate AND
ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd) >= #EndDate
THEN
(DATEDIFF(dd, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart), #EndDate) + 1)
-(DATEDIFF(wk, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart), #EndDate) * 2)
-(CASE WHEN DATENAME(dw, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart)) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart)) = 'Saturday' THEN 1 ELSE 0 END)
ELSE
(CASE WHEN ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart) >= #StartDate AND
ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd) <= #EndDate
THEN
(DATEDIFF(dd, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart), ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd)) + 1)
-(DATEDIFF(wk, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart), ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd)) * 2)
-(CASE WHEN DATENAME(dw, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart)) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart)) = 'Saturday' THEN 1 ELSE 0 END)
ELSE
(CASE WHEN ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart) <= #StartDate AND
ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd) <= #EndDate
THEN
(DATEDIFF(dd, #StartDate, ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd)) + 1)
-(DATEDIFF(wk, #StartDate, ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd)) * 2)
-(CASE WHEN DATENAME(dw, #StartDate) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, #StartDate) = 'Saturday' THEN 1 ELSE 0 END)
ELSE
(CASE WHEN ISNULL(AA.DDAreaActivityActualStart,AA.DDAreaActivityPlannedStart) <= #StartDate AND
ISNULL(AA.DDAreaActivityActualEnd,AA.DDAreaActivityPlannedEnd) >= #EndDate
THEN
(DATEDIFF(dd, #StartDate, #EndDate) + 1)
-(DATEDIFF(wk, #StartDate, #EndDate) * 2)
-(CASE WHEN DATENAME(dw, #StartDate) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, #StartDate) = 'Saturday' THEN 1 ELSE 0 END)
END) END) END) END) AS CalculatedDays
How about this
declare #StartDate date = '2016-03-21',
#EndDate date = '2016-03-25'
; with tbl (ProjectStartDate , ProjectEndDate) as
(
select '2016-03-13', '2016-03-22' union all
select '2016-03-22', '2016-03-29' union all
select '2016-03-13', '2016-03-29'
)
select *,
[working days] = datediff( day,
case when ProjectStartDate > #StartDate then ProjectStartDate else #StartDate end,
case when ProjectEndDate < #EndDate then ProjectEndDate else #EndDate end
) + 1
from tbl

How to make Query for that

I have a table structure from there i have to make a query in some different way
Table Structure
id unique identifier
code varchar(5) Not Null
Recording_date Datetime Not Null
Max_Temp numeric(5,2) Not Null
Min_Temp numeric(5,2) Not Null
We have some data as well in this table.We have data only for 2013 year and for first 3 months.
But the main thing is that i have to return's data in such a format like
Please help me to create a query for such a logic.
Thanks in advance.
Presuming you have one recording per day then
SELECT
DATEPART(m, Month_Start) + ' ' + DATEPART(yyyy, Month_Start)
, Max_Temp_Days
, CASE
WHEN Denominator = 0 THEN 0
ELSE (Max_Temp_Days / Denominator) * 100
END AS Percent_Max_Temp_Days
, Min_Temp_Days
, CASE
WHEN Denominator = 0 THEN 0
ELSE (Min_Temp_Days / Denominator) * 100
END AS Percent_Max_Temp_Days
FROM (
SELECT
DATEADD(MONTH, DATEDIFF(MONTH, 0, Recording_Date), 0) Month_Start
, Sum(CASE WHEN Max_Temp <= 0 THEN 1 END) Max_Temp_Days
, Sum(CASE WHEN Min_Temp <= 0 THEN 1 END) Min_Temp_Days
, COUNT(*) Denominator
FROM TemperatureRecordings
WHERE Recording_Date BETWEEN '2013-01-01' AND '2013-03-31'
GROUP BY DATEADD(MONTH, DATEDIFF(MONTH, 0, Recording_Date), 0)
) t
ORDER BY Month_Start
This works for all month data
DECLARE #maxTempratureTable table(monthName varchar(20), [No. of days Max<=0] int,[Percentage Max <=0] float)
INSERT INTO maxTempratureTable
SELECT RIGHT(CONVERT(VARCHAR, Recording_date, 106), 8) ,
COUNT(*) ,
COUNT(*) / DAY(DATEADD(mm,DATEDIFF(mm,-1,Recording_date),-1)) * 100
FROM tablename
WHERE Max_Temp <=0
GROUP BY RIGHT(CONVERT(VARCHAR, Recording_date, 106), 8)
DECLARE #minTempratureTable table(monthName varchar(20), [No. of days Min<=0] int,[Percentage Min<=0] float)
INSERT INTO #minTempratureTable
SELECT RIGHT(CONVERT(VARCHAR, Recording_date, 106), 8) ,
COUNT(*) ,
COUNT(*) / DAY(DATEADD(mm,DATEDIFF(mm,-1,Recording_date),-1)) * 100
FROM tablename
WHERE Min_Temp <=0
GROUP BY RIGHT(CONVERT(VARCHAR, Recording_date, 106), 8)
SELECT * FROM #minTempratureTable min
INNER JOIN #maxTempratureTable max
ON min.monthName = max.monthName
SELECT
MONTH(Recording_date),
SUM(CASE WHEN Max_Temp <= 0 THEN 1 ELSE 0 END),
SUM(CASE WHEN Max_Temp <= 0 THEN 1 ELSE 0 END) / COUNT(*),
SUM( CASE WHEN Min_Temp <= 0 THEN 1 ELSE 0 END ),
SUM( CASE WHEN Min_Temp <= 0 THEN 1 ELSE 0 END ) / COUNT(*)
FROM temperatures
GROUP BY MONTH(Recording_date)

Resources