Modify SQL code and queries in Microsoft SQL Server - sql

Please help and thank you very much!
How do I get this result?
http://i.stack.imgur.com/EedXW.png
This is my current result:
http://i.stack.imgur.com/Ydzn0.png
Code:
WITH shiftHours AS
(
SELECT
RowID,
y.EMPLOYEENAME AS EMPLOYEENAME,
-- flatten the first hour to remove the minutes and get the initial current hour
DATEADD(hour, DATEDIFF(hour, 0, ShiftA_Start), 0) AS currentHour,
ShiftA_Start,
ShiftA_End,
DATEPART(hour, ShiftA_Start) AS hourOrdinal,
-- determine how much of the first hour is applicable. if it is minute 0 then the whole hour counts
CAST(CASE
WHEN DATEADD(hour, DATEDIFF(hour, 0, ShiftA_Start), 0) = DATEADD(hour, DATEDIFF(hour, 0, ShiftA_End), 0) THEN DATEDIFF(minute, ShiftA_Start, ShiftA_End) / 60.0
WHEN DATEPART(minute, ShiftA_Start) = 0 THEN 1.0
ELSE (60 - DATEPART(minute, ShiftA_Start)) / 60.0
END AS DECIMAL(5,3)) AS hourValue
FROM
(-- use a ROW_NUMBER() to generate row IDs for the shifts to ensure each row is unique once it gets to the pivot
SELECT
ROW_NUMBER() OVER(ORDER BY ShiftA_Start, ShiftA_End) AS RowID,
EMPLOYEENAME,
ShiftA_Start,
ShiftA_End
FROM
(-- this is where the data gets pulled from the source table and where the data types are converted from string to DATETIME
SELECT
EMPLOYEENAME,
CONVERT(DATETIME, LEFT(SHIFTA_start, 17), 103) AS ShiftA_Start,
CONVERT(DATETIME, LEFT(SHIFTA_start, 17), 103) AS ShiftA_end,
CAST(CASE
WHEN DATEPART (day, [ShiftA_Start]) = DATEPART (day, [SHIFTA_END])
THEN CONVERT(DATETIME, LEFT(SHIFTA_end, 17), 103)
WHEN DATEPART (hour, [ShiftA_Start]) = DATEPART (hour, [SHIFTA_END])
THEN CONVERT(DATETIME, LEFT(SHIFTA_end, 17), 103) + '23:59:00.000' END AS VARCHAR(30)) AS S_END
FROM
[DatabaseName].[dbo].[TMS_PEOPLE]
WHERE
CONVERT(DATETIME, LEFT(SHIFTA_START, 17), 103) IS NOT NULL
AND CONVERT(DATETIME, LEFT(SHIFTA_END, 17), 103) IS NOT NULL
AND CONVERT(DATETIME, LEFT(SHIFTA_START, 17), 103) != CONVERT(DATETIME, LEFT(SHIFTA_END, 17), 103)
AND CONVERT(DATETIME, LEFT(SHIFTA_START, 17), 103) != '1900-01-01 00:00:00.000'
AND CONVERT(DATETIME, LEFT(SHIFTA_END, 17), 103) != '1900-01-01 00:00:00.000'
--AND CONVERT(DATETIME, LEFT(SHIFTA_start, 17), 103) = '2016-01-24 14:09:00.000'
AND EMPLOYEENAME = 'MUHAMMAD BIN PARMIN'
-- this is also where you would add any filtering from the source table such as date ranges
) x
) AS y
UNION ALL
SELECT RowID,
EMPLOYEENAME,
-- add an hour to the currentHour each time the recursive CTE is called
DATEADD(hour, 1, currentHour) AS currentHour,
ShiftA_Start,
ShiftA_End,
DATEPART(hour, DATEADD(hour, 1, currentHour)) AS hourOrdinal,
CAST(CASE
-- when this is the last time period determine the amount of the hour that is applicable
WHEN DATEADD(hour, 2, currentHour) > ShiftA_End THEN DATEPART(minute, ShiftA_End) / 60.0
ELSE 1
END AS DECIMAL(5,3)) AS hourValue
from shiftHours
-- contine recursion until the next hour is after the ShiftEnd
WHERE DATEADD(hour, 1, currentHour) < ShiftA_End
)
SELECT *
FROM (
SELECT RowID,
EMPLOYEENAME,
ShiftA_Start,
ShiftA_End,
hourValue,
hourOrdinal
from shiftHours
) AS t
PIVOT (
SUM(hourValue)
FOR hourOrdinal IN ([0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23])
) AS pvt
OPTION (MAXRECURSION 0);
JKQDJKBDJAJSDudkbsjkdbjkBhsjkdbnbjasadbjbdjajdbka dhajdkbobKJBDJBAJBDO

In your inner query you have this line
CONVERT(DATETIME, LEFT(SHIFTA_start, 17), 103) AS ShiftA_end,
should you not use the end of the shift instead?

Related

Group date by week as YYYY/MM/WK

I have made below query and its giving out put to show Year & Month.
I need to add week number also
select CONVERT(VARCHAR(7), DATEADD(MONTH, DATEDIFF(MONTH, 0, tqr_date), 0), 111) AS [Period Date],
REPLACE(RIGHT(CONVERT(VARCHAR(11), DATEADD(MONTH, DATEDIFF(MONTH, 0, tqr_date), 0), 106), 8), ' ', '-') AS Period,
Output will be 2019/02, Feb-2019
Expected output 2019/02/5,(where 1 is week number),
Week-05
you can try below - using concat DATEPART ( dw , getdate() )
select concat(CONVERT(VARCHAR(7), DATEADD(MONTH, DATEDIFF(MONTH, 0, getdate()), 0), 111),'/',
DATEPART ( dw , getdate() ) )
AS [Period Date],
REPLACE(RIGHT(CONVERT(VARCHAR(11),
DATEADD(MONTH, DATEDIFF(MONTH, 0, getdate()), 0), 106), 8), ' ', '-') AS Period
select Convert(varchar(20),getdate(),111) AS [Period Date],
DATEPART(WEEK, getdate()) - DATEPART(WEEK, DATEADD(MM, DATEDIFF(MM,0,getdate()), 0))+ 1 AS WEEK_OF_MONTH

SQL - AVG Output is incorrect

In below query, I am calculating the lead time between two different dates and eventually trying to get the average of that lead time but the output is incorrect.
SELECT
Round(AVG(CAST(
Case when CONVERT(datetime, ORDERDATE, 105) = CONVERT(datetime, INVOUTDATE, 105) THEN 0 else
Case when CONVERT(datetime, ORDERDATE, 105) + 1 = CONVERT(datetime, INVOUTDATE, 105) THEN 1 else
(DATEDIFF(dd, CONVERT(datetime, ORDERDATE, 105), CONVERT(datetime, INVOUTDATE, 105)))
-(DATEDIFF(wk, CONVERT(datetime, ORDERDATE, 105), CONVERT(datetime, INVOUTDATE, 105))*1)
-(CASE WHEN DATENAME(dw, CONVERT(datetime, ORDERDATE, 105)) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, CONVERT(datetime, INVOUTDATE, 105)) = 'Sunday' THEN 0 ELSE 0 END) end end AS FLOAT)),4) AS LEADTIME FROM DSORDERSTATUS
WHERE ORDERTYPE <> 'Exchange Order'
AND CONVERT(datetime, ORDERDATE, 105) between '20170801' and '20170831'
AND CONVERT(datetime, INVOUTDATE, 105) IS NOT NULL
To troubleshoot the above query I extract the data by using the same query below and when I manually calculate the lead time and average it was correct.
Don't know where is the issue? can someone please tell me whether anything wrong with my query.
Please click on the link to refer sample data Link
SELECT DISTINCT DOCKETNO,
Case when CONVERT(datetime, ORDERDATE, 105) = CONVERT(datetime, INVOUTDATE, 105) THEN 0 else
Case when CONVERT(datetime, ORDERDATE, 105) + 1 = CONVERT(datetime, INVOUTDATE, 105) THEN 1 else
(DATEDIFF(dd, CONVERT(datetime, ORDERDATE, 105), CONVERT(datetime, INVOUTDATE, 105)))
-(DATEDIFF(wk, CONVERT(datetime, ORDERDATE, 105), CONVERT(datetime, INVOUTDATE, 105))*1)
-(CASE WHEN DATENAME(dw, CONVERT(datetime, ORDERDATE, 105)) = 'Sunday' THEN 1 ELSE 0 END)
-(CASE WHEN DATENAME(dw, CONVERT(datetime, INVOUTDATE, 105)) = 'Sunday' THEN 0 ELSE 0 END) end end AS LEADTIME FROM DSORDERSTATUS
WHERE ORDERTYPE <> 'Exchange Order'
AND CONVERT(datetime, ORDERDATE, 105) between '20170801' and '20170831'
AND CONVERT(datetime, INVOUTDATE, 105) IS NOT NULL
ok, now I understand..
I think you have to group by orders before to calculate avg
;with
S AS (
select DOCKETNO, ORDERDATE, INVOUTDATE, COUNT(*) n
from DSORDERSTATUS where ORDERTYPE <> 'Exchange Order'
group by DOCKETNO, ORDERDATE, INVOUTDATE
),
D as (
select [DOCKETNO], [ORDERDATE], [INVOUTDATE],
DATEDIFF(dd, CONVERT(date, [ORDERDATE], 105), CONVERT(date, [INVOUTDATE], 105)) dd,
DATEDIFF(wk, CONVERT(date, [ORDERDATE], 105), CONVERT(date, [INVOUTDATE], 105)) wk,
CASE WHEN DATEPART(dw, CONVERT(datetime, ORDERDATE, 105)) = 7 THEN 1 ELSE 0 END IsSundayOrd,
CASE WHEN DATEPART(dw, CONVERT(datetime, INVOUTDATE, 105)) = 7 THEN 1 ELSE 0 END IsSundayInv
from S
)
select avg(cast(dd - case when dd>1 then (wk + IsSundayOrd + IsSundayInv) else 0 end as float)) leadtime
from D
where CONVERT(date, ORDERDATE, 105) between '20170801' and '20170831'
AND CONVERT(date, INVOUTDATE, 105) IS NOT NULL
I will try to convert your dates to DATE instesad of DATETIME I think you are filtering too much rows because '20170831' is '2017-08-31 00:00:00' and you are loosing all ORDERDATE between '00:00:00' and '23:59:59' (for '2017-08-31')
WHERE ORDERTYPE <> 'Exchange Order'
AND CONVERT(date, ORDERDATE, 105) between '20170801' and '20170831'
AND CONVERT(date, INVOUTDATE, 105) IS NOT NULL
With the help of MtwStark i was able to resolve this.
I have modified his query,
Thanks buddy
;with
S AS (
SELECT DISTINCT DOCKETNO,
Case when CONVERT(datetime, ORDERDATE, 105) = CONVERT(datetime, INVOUTDATE, 105) THEN 0 else
Case when CONVERT(datetime, ORDERDATE, 105) + 1 = CONVERT(datetime, INVOUTDATE, 105) THEN 1 else
(DATEDIFF(dd, CONVERT(datetime, ORDERDATE, 105), CONVERT(datetime, INVOUTDATE, 105)))
-(DATEDIFF(wk, CONVERT(datetime, ORDERDATE, 105), CONVERT(datetime, INVOUTDATE, 105))*1)
-(CASE WHEN DATENAME(dw, CONVERT(datetime, ORDERDATE, 105)) = 'Sunday' THEN 1 ELSE 0 END)end end AS LEADTIME FROM DSORDERSTATUS
WHERE ORDERTYPE <> 'Exchange Order'
AND CONVERT(datetime, ORDERDATE, 105) between '20170801' and '20170808'
AND CONVERT(datetime, INVOUTDATE, 105) IS NOT NULL
),
D AS (
SELECT DOCKETNO, LEADTIME FROM S
)
SELECT AVG(CAST(LEADTIME AS FLOAT)) FROM D

Split a column time into 2 (Time,Date)

how can i reformat this code to split results column time into 2 (Time,Date)
SELECT
DATEADD(mi, DATEDIFF(mi, 0, DATEADD(s, 2, dbo.roundtime
(CallStartTime, 1
))), 0) AS [Time], COUNT(DISTINCT [CallID]) AS [Sum of Calls]
FROM [Database].[dbo].[table]
WHERE CallStartTime BETWEEN '8/2/2015' AND '2/2/2016'
AND
CompanyID NOT IN
(718, 722, 1769, 1886, 2518, 2519, 2533, 2544, 2766, 2877, 3603, 3604, 4785, 5674, 5675, 5676, 5677, 5678, 5679, 5680, 5681,
5682, 5683, 5684, 5685, 5686, 5687, 5688, 5689, 5690, 5691, 5692, 9021, 9492, 9884, 4785, 11059, 11777, 11779, 13194
)
Convert is your friend:
select convert(char(10), getdate(), 120) dateComponent
, convert(char(5), getdate(), 108) timeComponent
Edit starts here:
For your question:
select convert(char(10), time, 120) dateComponent
, convert(char(5), time, 108) timeComponent
, "sum of calls"
from
(sql from the question goes here) temp

How to get list of 2nd and 4th Saturday dates in SQL Server?

I am almost a newbie to writing SQL queries.
In the context of SQL Server, how to get list of 2nd and 4th Saturday dates
in the year 2016?
Done as a derived table simply to show the logic but you can reduce if you prefer:
select *
from (
select d2016,
datename( weekday, d2016 ) as wkdy,
row_number( ) over ( partition by datepart( month, d2016 ), datename( weekday, d2016 ) order by d2016 ) as rn_dy_mth
from (
select dateadd( day, rn, cast( '2016-01-01' as date ) ) as d2016
from (
select row_number() over( order by object_id ) - 1 as rn
from sys.columns
) as rn
) as dy
) as dy_mth
where rn_dy_mth in ( 2, 4 )
and wkdy = 'Saturday'
order by d2016
--DEFINE LIMITS FOR DAY
DECLARE #TODATE DATETIME, #FROMDATE DATETIME
SET #FROMDATE ='2010-01-01'
SET #TODATE = '2017-12-31'
;WITH DATESEQUENCE( [DATE] ) AS
(
SELECT #FROMDATE AS [DATE]
UNION ALL
SELECT DATEADD(DAY, 1, [DATE])
FROM DATESEQUENCE
WHERE DATE < #TODATE
)
, DATESATURDAY AS
(SELECT CAST(CAST(YEAR([DATE]) AS VARCHAR)+
(CASE WHEN DATEPART(M,[DATE])<=9 THEN '0'+CAST(DATEPART(M,[DATE]) AS VARCHAR)
ELSE CAST(DATEPART(M,[DATE]) AS VARCHAR) END ) AS NUMERIC) AS MONTH_ID
,CONVERT(VARCHAR,[DATE],106) AS DAY_DESC
,UPPER(DATENAME(DW,[DATE]))AS DAY_NAME
FROM DATESEQUENCE )
,SECOND_FOURTH_SATURDAY AS
(SELECT *
,ROW_NUMBER() OVER (PARTITION BY MONTH_ID ORDER BY DAY_NAME) FALL_IN
FROM DATESATURDAY
WHERE DAY_NAME='SATURDAY')
SELECT * FROM SECOND_FOURTH_SATURDAY
WHERE FALL_IN IN(2,4)
OPTION (MAXRECURSION 10000)
You can get any Saturday of a month using the Following Query in SQL.
Here I'm Getting on Current Date, You can set your own selected date to get a Specific month Saturday
select DATEADD(dd, (14 - ##DATEFIRST - DATEPART(dw, DATEADD(MONTH, DATEDIFF(mm, 0,getdate()), 0))) % 7, DATEADD(MONTH, DATEDIFF(mm, 0, getdate()), 0)) as FirstSaturday,
DATEADD(dd,7,DATEADD(dd, (14 - ##DATEFIRST - DATEPART(dw, DATEADD(MONTH, DATEDIFF(mm, 0, getdate()), 0))) % 7, DATEADD(MONTH, DATEDIFF(mm, 0, getdate()), 0))) as SecondSaturday,
DATEADD(dd,14,DATEADD(dd, (14 - ##DATEFIRST - DATEPART(dw, DATEADD(MONTH, DATEDIFF(mm, 0, getdate()), 0))) % 7, DATEADD(MONTH, DATEDIFF(mm, 0, getdate()), 0))) as ThirdSaturday,
DATEADD(dd,21,DATEADD(dd, (14 - ##DATEFIRST - DATEPART(dw, DATEADD(MONTH, DATEDIFF(mm, 0, getdate()), 0))) % 7, DATEADD(MONTH, DATEDIFF(mm, 0, getdate()), 0))) as LastSaturday

Rounding milliseconds SQL Server 2000

In Microsoft SQL Server 2000, I have this data.
1900-01-01 00:10:10.830
1900-01-01 00:10:10.430
From the above column, I want to select the datetime and round off the milliseconds, in order to get the below output
1900-01-01 00:10:11
1900-01-01 00:10:10
Thanks in advance
For SQL Server 2008 and above, you can do use DATETIME2. DATETIME2 is available in SQL Server 2008 and above - for more info see here:
SELECT CAST('1900-01-01 00:10:10.830' AS DATETIME2(0));
SELECT CAST('1900-01-01 00:10:10.430' AS DATETIME2(0));
Confirmed Output
For earlier version of SQL Sever, for example SQL Server 2000. You can do something like this:
SELECT DATEADD(ms, -DATEPART(ms, DATEADD(ms, 500, CAST('1900-01-01 00:10:10.830' AS DATETIME))) , DATEADD(ms, 500, CAST('1900-01-01 00:10:10.830' AS DATETIME)));
SELECT DATEADD(ms, -DATEPART(ms, DATEADD(ms, 500, CAST('1900-01-01 00:10:10.430' AS DATETIME))) , DATEADD(ms, 500, CAST('1900-01-01 00:10:10.430' AS DATETIME)));
SELECT *
, DateAdd(ss, rounded_second, round_down_seconds) As result
FROM (
SELECT *
, Round(nanoseconds / 1000.0, 0) As rounded_second
FROM (
SELECT the_date
, DatePart(ms, the_date) As nanoseconds
, DateAdd(ss, DateDiff(ss, 0, the_date), 0) As round_down_seconds
FROM (
SELECT '1900-01-01 00:10:10.830' As the_date
UNION ALL
SELECT '1900-01-01 00:10:10.430'
) As x
) As y
) As z
I've split out each step to be as clear as possible.
If you want a single liner:
SELECT the_date
, DateAdd(ss, Round(DatePart(ms, the_date) / 1000.0, 0), DateAdd(ss, DateDiff(ss, 0, the_date), 0)) As result
FROM (
SELECT '1900-01-01 00:10:10.830' As the_date
UNION ALL
SELECT '1900-01-01 00:10:10.430'
) As x