SQL to return 1 for each row with column range in 2017 or 2018 or 2019 - sql

I have a query that looks like this:
SELECT DISTINCT
p.person_ID
,p.Last_Name
,ISNULL(p.Middle_Initial, '') AS Middle
,p.First_Name
,sh.Status_from_date
,sh.Status_thru_date
--(a)
FROM
person p
INNER JOIN
Person_Facilities f ON p.Person_ID = f.Person_ID
LEFT OUTER JOIN
rv_person_status_hist sh ON p.person_ID = sh.person_ID
ORDER BY
Last_Name
The returned data looks like this sort of thing (ignore the 2018 column for now):
Person_id Last_Name Middle First_Name Status_from_date Status_thru_date 2018
8000 Skywalker Dude Luke Null 2010-01-28 07:38 1
9000 Yoda Phinnius 2017-06-01 00:00 2019-05-31 00:00 1
1000 Lamb Little Mary 2018-07-01 00:00 2020-06-30 00:00 1
2000 Spider Bitsy Itsy 2016-11-01 00:00 2017-06-30 00:00 1
How do I add a column, say [2018], and put a 1 for if status_from_date to status_thru_date is in 2018, or a 0 if not?
I wanted to add the following at the --(a) in the query:
,(SELECT case
when exists
(
select * --
FROM dbo.RV_Person_status_hist
where
status_from_date is not null
and
('1-1-2018' between status_from_date and status_thru_date)
and status_from_date is not null
)
then 1 else 0 end )
AS [2018]
This doesn't seem to be working, though. See the 2018 column in the above table. It's showing 1 for all returned, and it's not excluding nulls. It's pretty complicated. status_from and status_thru could fall with 2018 in it, or 2018 could be inside status_from and status_thru, which should both be 1.
How do I exclude the nulls, and how do I show a 1 when the status date includes 2018?
I've looked at range within range, and return 0 or 1. I don't think I have all cases since the ranges overlap as well.
**Update:
I tried adding this at --(a) above instead, per the potential answer below:
,(SELECT status_from_date, status_thru_date,
case
when datepart(year, status_from_date)='2018'
or datepart(year, status_thru_date)='2018'
or (
status_from_date <= '01/01/2018'
and status_thru_date >= '12/12/2018'
)
then 1
else 0
end) AS [2018]
but I'm getting Ambiguous column name 'status_from_date'. Ambiguous
column name 'status_thru_date'. Only one expression can be specified
in the select list when the subquery is not introduced with EXISTS.
Any ideas? Figured it out.
**Update 2: How about this?
,(case when (
(
(sh.status_from_date is null or sh.status_from_date <= '2017-01-01') and
(sh.status_thru_date is null or sh.status_thru_date >= '2017-12-31')
)
or
(
(f.status_from_date is null or f.status_from_date <= '2017-01-01') and
(f.status_thru_date is null or f.status_thru_date >= '2017-12-31')
)
or
(
(datepart(year, sh.status_from_date)='2017') or
(datepart(year, sh.status_thru_date)='2017') or
(datepart(year, f.status_from_date)='2017') or
(datepart(year, f.status_from_date)='2017')
)
and
p.Sex='M'
)
then 1 else 0
end) as [2017_Male]
,(case when (
(
(sh.status_from_date is null or sh.status_from_date <= '2017-01-01') and
(sh.status_thru_date is null or sh.status_thru_date >= '2017-12-31')
)
or
(
(f.status_from_date is null or f.status_from_date <= '2017-01-01') and
(f.status_thru_date is null or f.status_thru_date >= '2017-12-31')
)
or
(
(datepart(year, sh.status_from_date)='2017') or
(datepart(year, sh.status_thru_date)='2017') or
(datepart(year, f.status_from_date)='2017') or
(datepart(year, f.status_from_date)='2017')
)
and
p.Sex='F'
)
then 1 else 0
end) as [2017_Female]--------
That one is putting a 1 in the 2017 column for both male and female for the data of: status_from: 2014-10-01 and status_to: 2016-09-30

You could do something like this:
while would be to check if start or end contains 2018, or if the date is between start and thru
CREATE TABLE #testTable (
Status_from_date DATETIME,
Status_thru_date DATETIME
)
INSERT INTO #testTable (
Status_from_date,
Status_thru_date
)
VALUES (
'2017-06-01 00:00',
'2019-05-31 00:00'
),
(
NULL,
'2010-01-28 07:38'
),
(
'2018-07-01 00:00',
'2020-06-30 00:00'
)
SELECT Status_from_date,
Status_thru_date,
CASE
WHEN datepart(year, Status_from_date) = '2018'
OR datepart(year, Status_thru_date) = '2018'
OR (
Status_from_date <= '01/01/2018'
AND Status_thru_date >= '12/12/2018'
)
THEN 1
ELSE 0
END AS '2018'
FROM #testTable
DROP TABLE #testTable
which produces:
Status_from_date Status_thru_date 2018
2017-06-01 00:00:00.000 2019-05-31 00:00:00.000 1
NULL 2010-01-28 07:38:00.000 0
2018-07-01 00:00:00.000 2020-06-30 00:00:00.000 1

If you want any overlaps in 2018, then:
(case when (status_from_date is null or status_from_date < '2019-01-01') and
(status_to_date is null or status_to_date >= '2018-01-01')
then 1 else 0
end) as is_2018
If you want overlaps of the complete year:
(case when (status_from_date is null or status_from_date <= '2018-01-01') and
(status_to_date is null or status_to_date >= '2018-12-31')
then 1 else 0
end) as is_2018

Related

Sql Pivot on time

Table 1: Daily attendance data:
att_date emp_code emp_name in_time out_time
2018-10-21 9999 Test 2018-10-21 08:00:00.000 2018-10-22 06:00:00.000
Table 2: Trnevents
emp_readr_id DT EVENTID
9999 2018-10-24 07:00:00.000 0
9999 2018-10-24 05:00:00.000 0
9999 2018-10-24 03:00:00.000 0
9999 2018-10-23 21:00:00.000 0
9999 2018-10-23 19:00:00.000 0
9999 2018-10-23 06:00:00.000 0
9999 2018-10-22 06:00:00.000 0
9999 2018-10-21 08:00:00.000 0
I used this query to get all times in between in time and out time ,below query works fine but i try to make in row by using pivot. While using pivot out time shows in next row.
declare #tempProcesstable as table(
[id] [nvarchar](200) NULL,
[time_stamp] datetime NULL,
[AccessType] varchar(3) NULL)
insert into #tempProcesstable
select distinct t1.emp_Reader_id, t1.DT,t1.eventid from daily_attendance_data t2 join trnevents t1
on t1.emp_reader_id=t2.emp_reader_id where (CONVERT(VARCHAR(26), t2.att_Date, 23) >=CONVERT(VARCHAR(26), '2018-10-20', 23)
and CONVERT(VARCHAR(26), t2.att_date, 23) <=CONVERT(VARCHAR(26), '2018-10-21', 23))
and
(t1.DT >=t2.in_time
and t1.DT <=t2.out_time)
-- and t1.emp_reader_id=1000
group by t1.emp_Reader_id,t1.dt,t1.eventid order by t1.emp_reader_id,DT asc
; With CheckIns
As (Select Rowemp_reader_id = Row_Number() Over (Partition by id, Cast(time_stamp As Date) Order By time_stamp),
id, time_stamp,
[Date] = Cast(time_stamp As Date),
[Time] = Cast(time_stamp As Time(0))
From #tempProcesstable)
Select Pvt.id,B.emp_name , [Date], CHECK1, CHECK2,Cast(dateadd(ss,datediff(ss,CHECK1,CHECK2),0) As Time(0)) Total1,
CHECK3, CHECK4,Cast(dateadd(ss,datediff(ss,CHECK3,CHECK4),0) As Time(0)) Total2
From (Select id, [Date], [Time],
CHECKNum = 'CHECK' + Cast(Rowemp_reader_id As varchar(11))
From CheckIns) As P
Pivot (Min([Time])
For CheckNum In (Check1, [Check2], Check3, Check4)
) As Pvt
LEFT OUTER JOIN
dbo.employee AS B ON Pvt.id= B.emp_reader_id
My output:
id emp_name Date CHECK1 CHECK2 Total1 CHECK3 CHECK4 Total2
1048 Singh 2018-10-21 07:06:07 17:34:05 10:27:58 NULL NULL NULL
9999 Test 2018-10-21 08:00:00 NULL NULL NULL NULL NULL NULL
9999 Test 2018-10-22 06:00:00 NULL NULL NULL NULL NULL NULL
Expected output:
I want all times between in time and out time in night to morning also.
can any one help me to rectify this.
id emp_name Date CHECK1 CHECK2 Total1 CHECK3 CHECK4 Total2
1048 Singh 2018-10-21 07:06:07 17:34:05 10:27:58 NULL NULL NULL
9999 Test 2018-10-21 08:00:00 06:00:00 NULL NULL NULL NULL NULL
You can try to use ROW_NUMBER() window function make row number by each date.
then use condition aggregate function to do pivot
SELECT emp_readr_id,
emp_name,
[Date],
MAX(CASE WHEN RN = 1 THEN time END) CHECK1,
MAX(CASE WHEN RN = 2 THEN time END) CHECK2,
MAX(CASE WHEN RN = 3 THEN time END) CHECK3,
MAX(CASE WHEN RN = 4 THEN time END) CHECK4
FROM (
SELECT emp_readr_id,
emp_name,
CONVERT(VARCHAR(10),DT,120) 'Date',
ROW_NUMBER() OVER(PARTITION BY CONVERT(VARCHAR(10),DT,120) ORDER BY DT) rn,
CONVERT(VARCHAR(10),DT,108) time
FROM Daily d
JOIN Trnevents t on t.DT between d.in_time and d.out_time
) t1
group by emp_readr_id,
emp_name,
[Date]
sqlifddle

SQL how to count census points occurring between date records

I’m using MS-SQL-2008 R2 trying to write a script that calculates the Number of Hospital Beds occupied on any given day, at 2 census points: midnight, and 09:00.
I’m working from a data set of patient Ward Stays. Basically, each row in the table is a record of an individual patient's stay on a single ward, and records the date/time the patient is admitted onto the ward, and the date/time the patient leaves the ward.
A sample of this table is below:
Ward_Stay_Primary_Key | Ward_Start_Date_Time | Ward_End_Date_Time
1 | 2017-09-03 15:04:00.000 | 2017-09-27 16:55:00.000
2 | 2017-09-04 18:08:00.000 | 2017-09-06 18:00:00.000
3 | 2017-09-04 13:00:00.000 | 2017-09-04 22:00:00.000
4 | 2017-09-04 20:54:00.000 | 2017-09-08 14:30:00.000
5 | 2017-09-04 20:52:00.000 | 2017-09-13 11:50:00.000
6 | 2017-09-05 13:32:00.000 | 2017-09-11 14:49:00.000
7 | 2017-09-05 13:17:00.000 | 2017-09-12 21:00:00.000
8 | 2017-09-05 23:11:00.000 | 2017-09-06 17:38:00.000
9 | 2017-09-05 11:35:00.000 | 2017-09-14 16:12:00.000
10 | 2017-09-05 14:05:00.000 | 2017-09-11 16:30:00.000
The key thing to note here is that a patient’s Ward Stay can span any length of time, from a few hours to many days.
The following code enables me to calculate the number of beds at both census points for any given day, by specifying the date in the case statement:
SELECT
'05/09/2017' [Date]
,SUM(case when Ward_Start_Date_Time <= '05/09/2017 00:00:00.000' AND (Ward_End_Date_Time >= '05/09/2017 00:00:00.000' OR Ward_End_Date_Time IS NULL)then 1 else 0 end)[No. Beds Occupied at 00:00]
,SUM(case when Ward_Start_Date_Time <= '05/09/2017 09:00:00.000' AND (Ward_End_Date_Time >= '05/09/2017 09:00:00.000' OR Ward_End_Date_Time IS NULL)then 1 else 0 end)[No. Beds Occupied at 09:00]
FROM
WardStaysTable
And, based on the sample 10 records above, generates this output:
Date | No. Beds Occupied at 00:00 | No. Beds Occupied at 09:00
05/09/2017 | 4 | 4
To perform this for any number of days is obviously onerous, so what I’m looking to create is a query where I can specify a start/end date parameter (e.g. 1st-5th Sept), and for the query to then evaluate the Ward_Start_Date_Time and Ward_End_Date_Time variables for each record, and – grouping by the dates defined in the date parameter – count each time the 00:00:00.000 and 09:00:00.000 census points fall between these 2 variables, to give an output something along these lines (based on the above 10 records):
Date | No. Beds Occupied at 00:00 | No. Beds Occupied at 09:00
01/09/2017 | 0 | 0
02/09/2017 | 0 | 0
03/09/2017 | 0 | 0
04/09/2017 | 1 | 1
05/09/2017 | 4 | 4
I’ve approached this (perhaps naively) thinking that if I use a cte to create a table of dates (defined by the input parameters), along with associated midnight and 9am census date/time points, then I could use these variables to group and evaluate the dataset.
So, this code generates the grouping dates and census date/time points:
DECLARE
#StartDate DATE = '01/09/2017'
,#EndDate DATE = '05/09/2017'
,#0900 INT = 540
SELECT
DATEADD(DAY, nbr - 1, #StartDate) [Date]
,CONVERT(DATETIME,(DATEADD(DAY, nbr - 1, #StartDate))) [MidnightDate]
,DATEADD(mi, #0900,(CONVERT(DATETIME,(DATEADD(DAY, nbr - 1, #StartDate))))) [0900Date]
FROM
(
SELECT
ROW_NUMBER() OVER ( ORDER BY c.object_id ) AS nbr
FROM sys.columns c
) nbrs
WHERE nbr - 1 <= DATEDIFF(DAY, #StartDate, #EndDate)
The stumbling block I’ve hit is how to join the cte to the WardStays dataset, because there’s no appropriate key… I’ve tried a few iterations of using a subquery to make this work, but either I’m taking the wrong approach or I’m getting my syntax in a mess.
In simple terms, the logic I’m trying to create to get the output is something like:
SELECT
[Date]
,SUM (case when WST.Ward_Start_Date_Time <= [MidnightDate] AND (WST.Ward_End_Date_Time >= [MidnightDate] OR WST.Ward_End_Date_Time IS NULL then 1 else 0 end) [No. Beds Occupied at 00:00]
,SUM (case when WST.Ward_Start_Date_Time <= [0900Date] AND (WST.Ward_End_Date_Time >= [0900Date] OR WST.Ward_End_Date_Time IS NULL then 1 else 0 end) [No. Beds Occupied at 09:00]
FROM WardStaysTable WST
GROUP BY [Date]
Is the above somehow possible, or am I barking up the wrong tree and need to take a different approach altogether? Appreciate any advice.
I would expect something like this:
WITH dates as (
SELECT CAST(#StartDate as DATETIME) as dte
UNION ALL
SELECT DATEADD(DAY, 1, dte)
FROM dates
WHERE dte < #EndDate
)
SELECT dates.dte [Date],
SUM(CASE WHEN Ward_Start_Date_Time <= dte AND
Ward_END_Date_Time >= dte
THEN 1 ELSE 0
END) as num_beds_0000,
SUM(CASE WHEN Ward_Start_Date_Time <= dte + CAST('09:00' as DATETIME) AND
Ward_END_Date_Time >= dte + CAST('09:00' as DATETIME)
THEN 1 ELSE 0
END) as num_beds_0900
FROM dates LEFT JOIN
WardStaysTable wt
ON wt.Ward_Start_Date_Time <= DATEADD(day, 1, dates.dte) AND
wt.Ward_END_Date_Time >= dates.dte
GROUP BY dates.dte
ORDER BY dates.dte;
The cte is just creating the list of dates.
What a cool exercise. Here is what I came up with:
CREATE TABLE #tmp (ID int, StartDte datetime, EndDte datetime)
INSERT INTO #tmp values(1,'2017-09-03 15:04:00.000','2017-09-27 06:55:00.000')
INSERT INTO #tmp values(2,'2017-09-04 08:08:00.000','2017-09-06 18:00:00.000')
INSERT INTO #tmp values(3,'2017-09-04 13:00:00.000','2017-09-04 22:00:00.000')
INSERT INTO #tmp values(4,'2017-09-04 20:54:00.000','2017-09-08 14:30:00.000')
INSERT INTO #tmp values(5,'2017-09-04 20:52:00.000','2017-09-13 11:50:00.000')
INSERT INTO #tmp values(6,'2017-09-05 13:32:00.000','2017-09-11 14:49:00.000')
INSERT INTO #tmp values(7,'2017-09-05 13:17:00.000','2017-09-12 21:00:00.000')
INSERT INTO #tmp values(8,'2017-09-05 23:11:00.000','2017-09-06 07:38:00.000')
INSERT INTO #tmp values(9,'2017-09-05 11:35:00.000','2017-09-14 16:12:00.000')
INSERT INTO #tmp values(10,'2017-09-05 14:05:00.000','2017-09-11 16:30:00.000')
DECLARE
#StartDate DATE = '09/01/2017'
,#EndDate DATE = '10/01/2017'
, #nHours INT = 9
;WITH d(OrderDate) AS
(
SELECT DATEADD(DAY, n-1, #StartDate)
FROM (SELECT TOP (DATEDIFF(DAY, #StartDate, #EndDate) + 1)
ROW_NUMBER() OVER (ORDER BY [object_id]) FROM sys.all_objects) AS x(n)
)
, CTE AS(
select OrderDate, t2.*
from #tmp t2
cross apply(select orderdate from d ) d
where StartDte >= #StartDate and EndDte <= #EndDate)
select OrderDate,
SUM(CASE WHEN OrderDate >= StartDte and OrderDate <= EndDte THEN 1 ELSE 0 END) [No. Beds Occupied at 00:00],
SUM(CASE WHEN StartDTE <= DateAdd(hour,#nHours,CAST(OrderDate as datetime)) and DateAdd(hour,#nHours,CAST(OrderDate as datetime)) <= EndDte THEN 1 ELSE 0 END) [No. Beds Occupied at 09:00]
from CTE
GROUP BY OrderDate
This should allow you to check for any hour of the day using the #nHours parameter if you so choose. If you only want to see records that actually fall within your date range then you can filter the cross apply on start and end dates.

Function to count if X amount amount of days as a full month

We offer services for clients and each client has an Authorization for 90 days
I want to create a function which counts 15 days as full months.
For example, let’s say a client get Authorization on 10/17/2017. It’s means it’s less than 15 days for October so that Authorization will not count for October, but it has to count for November, December and January 2018.
;WITH CTE AS (
select
d.ClientId,
LOC
datediff(day, l.DecisionOn, d.duedate) 'Days',
l.DecisionOn,
d.duedate
from code d
join codeloc l on d.curdocversionid = l.docversionid
join codeaccess a on a.docversionid = d.curdocversionid
where codeid = 69999
and aoca in ('68','69','70','71','72','74')
),
T AS (
SELECT ClientId, LOC, COUNT(*) CNT FROM CTE
WHERE [Days] > 15
AND AuthorizedDecisionOn > DATEADD(MONTH, (CASE WHEN DAY(GETDATE()) > 15 THEN 1 ELSE 0 END) , CAST( GETDATE() as date))
AND duedate < DATEADD(MONTH,3 + (CASE WHEN DAY(GETDATE()) > 15 THEN 1 ELSE 0 END) , CAST( GETDATE() as date))
GROUP BY ClientId, LOC
)
Here's an inline table valued function (iTvf) that will give you what you need.
(note: I use iTvf's because they outperform scalar udfs)
CREATE FUNCTION dbo.monthsBetweenMinDay
(
#fromDate date,
#toDate date,
#minDays tinyint
)
RETURNS TABLE WITH SCHEMABINDING AS RETURN
SELECT Months = m.mb +
CASE WHEN DATEDIFF(day,d.fd,dateadd(month, -m.mb, d.td)) >= #minDays THEN 1 ELSE 0 END
FROM (VALUES (#fromDate, #toDate)) d(fd,td) -- from date and todate
CROSS APPLY (VALUES(
CASE WHEN d.fd > d.td THEN NULL
WHEN DATEPART(day, d.fd) > DATEPART(day, d.td) THEN DATEDIFF(month, d.fd, d.td)-1
ELSE DATEDIFF(month, d.fd, d.td) END)) m(mb);
Here's an example of the function in action:
-- sample data
CREATE TABLE #dates (date1 date, date2 date);
INSERT #dates
SELECT dt.dt, CAST(DATEADD(day, [days].d, DATEADD(month, months.m, dt.dt)) as date)
FROM (VALUES ('20170101')) dt(dt), (VALUES (4),(15),(25)) [days](d), (VALUES(0),(1),(4)) months(m);
-- solution
SELECT *
FROM #dates d
CROSS APPLY dbo.monthsBetweenMinDay(d.date1, d.date2, 15);
Results
date1 date2 Months
---------- ---------- -----------
2017-01-01 2017-01-05 0
2017-01-01 2017-01-16 1
2017-01-01 2017-01-26 1
2017-01-01 2017-02-05 1
2017-01-01 2017-02-16 2
2017-01-01 2017-02-26 2
2017-01-01 2017-05-05 4
2017-01-01 2017-05-16 5
2017-01-01 2017-05-26 5

Tolerance with Min Max

I am trying to adjust the below code by adding a 2 week tolerance piece.
What it does it looks when the first time a customer (identifier) created a request and the first time it was completed and counts the days which happened in between.
However I am trying to add a tolerance piece. Which says count the number of NCO which occurred between those dates and if there were further requests past the completion date which happened within 2 weeks of the completion date then count those as well (part of the same request). Anything past 2 weeks of the completions date consider as a new request.
CREATE TABLE #temp
(
Identifier varchar(40)NOT NULL
,Created_Date DATETIME NOT NULL
,Completed_Date DATETIME NULL
,SN_Type varchar(20) NOT NULL
,SN_Status varchar(20) NOT NULL
)
;
INSERT INTO #temp
VALUES ('3333333','2017-02-14 15:00:40.000','2017-02-15 00:00:00.000','Re-Activattion', 'COMP');
INSERT INTO #temp
VALUES ('3333333','2017-05-24 16:41:04.000','2017-06-05 00:00:00.000','Re-Activattion', 'N-CO');
INSERT INTO #temp
VALUES ('3333333','2017-05-25 11:49:54.000','2017-05-26 00:00:00.000','Re-Activattion', 'COMP');
INSERT INTO #temp
VALUES ('3333333','2017-06-27 10:24:29.000',NULL,'Re-Activattion', 'ACC');
#Alex you code is accurate just I would like to be selecting the min date the record is created a 2nd time, so line 2 of the result should return min date to be 2017-05-24 16:41:04.000.
select identifier
,case
when sum(case when SN_STATUS='COMP' and SN_TYPE = 'Re-Activattion' then 1 else 0 end)>0
then str(datediff(day
,MIN(case
when SN_TYPE = 'Re-Activattion'
then Created_Date
else null
end
)
,min(case
when (SN_TYPE = 'Re-Activattion'
and SN_STATUS='COMP'
)
then Completed_Date
else null
end
)
)
)
when sum(case when SN_TYPE='Re-Activattion' then 1 else 0 end)>0
then 'NOT COMP'
else 'NO RE-ACT'
end
as RE_ACT_COMPLETION_TIME
,Sum(CASE WHEN SN_STATUS = 'N-CO' THEN 1 ELSE 0 END) as [RE-AN NCO #]
from #temp
group by identifier
;
RESULTS I AM AFTER:
Your table design is not optimal for these kinds of queries as there is no definitive record that specified order start and order end. Additionally multiple orders are stored with the same identifier.
To work around this you need to calculate/identify Order start and Order End records yourself.
One way to do it is using Common Table Expressions.
Note: I have added comments to code to explain what each section does.
-- calculate/identify Order start and Order End records
WITH cte AS
(
-- 1st Order start record i.e. earliest record in the table for a given "Identifier"
SELECT Identifier, MIN( Created_Date ) AS Created_Date, CONVERT( VARCHAR( 30 ), 'Created' ) AS RecordType, 1 AS OrderNumber
FROM #temp
GROUP BY Identifier
UNION ALL
-- All records with "COMP" status are treated as order completed events. Add 2 weeks to the completed date to create a "dummy" Order End Date
SELECT Identifier, DATEADD( WEEK, 2, Created_Date ) AS Created_Date, 'Completed' AS RecordType, ROW_NUMBER() OVER( PARTITION BY Identifier ORDER BY Created_Date ) AS OrderNumber
FROM #temp
WHERE SN_STATUS = 'COMP'
UNION ALL
-- Set the start period of the next order to be right after (3 ms) the previous Order End Date
SELECT Identifier, DATEADD( ms, 3, DATEADD( WEEK, 2, Created_Date )) AS Created_Date, 'Created' AS RecordType, ROW_NUMBER() OVER( PARTITION BY Identifier ORDER BY Created_Date ) + 1 AS OrderNumber
FROM #temp
WHERE SN_STATUS = 'COMP'
),
-- Combine Start / End records into one record
OrderGroups AS(
SELECT Identifier, OrderNumber, MIN( Created_Date ) AS OrderRangeStartDate, MAX( Created_Date ) AS OrderRangeEndDate
FROM cte
GROUP BY Identifier, OrderNumber
)
SELECT a.Identifier, a.OrderNumber, OrderRangeStartDate, OrderRangeEndDate,
case
when sum(case when SN_STATUS='COMP' and SN_TYPE = 'Re-Activattion' then 1 else 0 end)>0
then str(datediff(day
,MIN(case
when SN_TYPE = 'Re-Activattion'
then Created_Date
else null
end
)
,min(case
when (SN_TYPE = 'Re-Activattion'
and SN_STATUS='COMP'
)
then Completed_Date
else null
end
)
)
)
when sum(case when SN_TYPE='Re-Activattion' then 1 else 0 end)>0
then 'NOT COMP'
else 'NO RE-ACT'
end as RE_ACT_COMPLETION_TIME,
Sum(CASE WHEN SN_STATUS = 'N-CO' THEN 1 ELSE 0 END) as [RE-AN NCO #]
FROM OrderGroups AS a
INNER JOIN #Temp AS b ON a.Identifier = b.Identifier AND a.OrderRangeStartDate <= b.Created_Date AND b.Created_Date <= a.OrderRangeEndDate
GROUP BY a.Identifier, a.OrderNumber, OrderRangeStartDate, OrderRangeEndDate
Output:
Identifier OrderNumber OrderRangeStartDate OrderRangeEndDate RE_ACT_COMPLETION_TIME RE-AN NCO #
-------------- ------------- ----------------------- ----------------------- ---------------------- -----------
200895691 1 2016-01-27 14:25:00.000 2016-02-10 15:15:00.000 0 2
200895691 2 2016-02-10 15:15:00.003 2017-01-16 12:15:00.000 1 1
Output for the updated data set:
Identifier OrderNumber OrderRangeStartDate OrderRangeEndDate RE_ACT_COMPLETION_TIME RE-AN NCO #
------------ ------------ ----------------------- ----------------------- ---------------------- -----------
200895691 1 2017-01-11 00:00:00.000 2017-03-27 00:00:00.000 61 4
200895691 2 2017-03-27 00:00:00.003 2017-04-20 00:00:00.000 1 1
3333333 1 2017-01-27 00:00:00.000 2017-02-10 00:00:00.000 0 2
44454544 1 2017-01-27 00:00:00.000 2017-01-27 00:00:00.000 NOT COMP 1
7777691 1 2017-02-08 09:36:44.000 2017-02-22 09:36:44.000 63 1
Update 2017-10-05 in response to the comment
Input:
INSERT INTO #temp VALUES
('11111','20170203','20170203','Re-Activattion', 'COMP'),
('11111','20170206','20170202','Re-Activattion', 'N-CO');
Output:
Identifier OrderNumber OrderRangeStartDate OrderRangeEndDate RE_ACT_COMPLETION_TIME RE-AN NCO #
---------- ------------ ----------------------- ----------------------- ---------------------- -----------
11111 1 2017-02-03 00:00:00.000 2017-02-17 00:00:00.000 0 1

Data according to time

I have table1 in this data is
ID Name StartDate EndDate
1 Paris 2014-02-01 00:00:00.000 2014-02-28 23:59:59.000
2 UK 2014-02-01 00:00:00.000 2014-02-28 23:59:59.000
3 France 2014-02-01 00:00:00.000 2014-02-28 23:59:59.000
and sp is
ALTER procedure [dbo].[spdata]
#fromdate datetime,
#todate datetime,
#Region varchar(50)
as
Select (Select Sum(Convert(int,SF)) from RVU inner dbo.VI vh on RVU.FID = vh.FID WHERE vh.No = Q.No and ID in (
Select ID from RU WHERE CAST(StartDate as date)>= CAST(#fromdate as date) and CAST(EndDate as date)<= CAST(#todate as date)
)) as SF
from (
Select
S.Name,
S.No,
SUM(Case when s.Vme='Car' then total else 0 end) as CAR,
SUM(Case when s.Vme='Tin' then total else 0 end) as Tin,
SUM(Case when s.Vme='Cake' then total else 0 end) as Cake,
SUM(Case when s.Vme='Flow' then total else 0 end) as Flow,
SUM(Case when s.Vme='Unit' then total else 0 end) as Unit,
SUM(total) total ,
MAX(S.Speed) Speed
from (
Select vh.Name as Name,vh.No as No,VV.Vame,count(VV.Vme) as total, RV.SF as MA,
RV.Speed from VVU VV inner join RVU RV on VV.MID=RV.ID inner join RU RU on RV.ID=RU.ID
left join dbo.VI vh on RV.FID = vh.FID WHERE CAST(RU.StartDate as date)>= CAST(#fromdate as date) and CAST(RU.EndDate as date)<= CAST(#todate as date) and
RU.Name_C= #Name_C AND Vme <> '' Group By vh.Name, vh.No, VV.Vme, RV.SF,
RV.Speed ) S GROUP BY s.RegNo, s.Name) Q
from that sp when i enter parameters DATA IS
[spdata] '2016-07-01 00:00:00.000', '2016-07-31 23:59:59.000', 'pARIS'
Name No CAR Tin Cake Flow Unit total Speed SF
John 412 0 0 12 0 5 17 82 60
Mike 48 2 1 5 1 3 9 160 464
ACNme 438 0 1 5 2 3 11 10 264
XYZ 248 0 1 5 3 3 12 60 244
now i want when i change time '2016-07-01 00:00:00.000', '2016-07-31 23:59:59.000',
like this
'2016-07-01 02:02:00.000', '2016-07-31 12:59:59.000',
then records also reflect on this time means according to date plus time data will be display
Don't cast your StartDate , EndDate , #fromdate , #todate as Date.
`Alter procedure [dbo].[spdata]
#fromdate datetime,
#todate datetime,
#Region varchar(50)
as
Select (Select Sum(Convert(int,SF)) from RVU inner dbo.VI vh on RVU.FID = vh.FID WHERE vh.No = Q.No and ID in (
Select ID from RU WHERE StartDate >= #fromdate and EndDate <=#todate
)) as SF
from (
Select
S.Name,
S.No,
SUM(Case when s.Vme='Car' then total else 0 end) as CAR,
SUM(Case when s.Vme='Tin' then total else 0 end) as Tin,
SUM(Case when s.Vme='Cake' then total else 0 end) as Cake,
SUM(Case when s.Vme='Flow' then total else 0 end) as Flow,
SUM(Case when s.Vme='Unit' then total else 0 end) as Unit,
SUM(total) total ,
MAX(S.Speed) Speed
from (
Select vh.Name as Name,vh.No as No,VV.Vame,count(VV.Vme) as total, RV.SF as MA,
RV.Speed from VVU VV inner join RVU RV on VV.MID=RV.ID inner join RU RU on RV.ID=RU.ID
left join dbo.VI vh on RV.FID = vh.FID WHERE RU.StartDate >= #fromdate and RU.EndDate <= #todate and
RU.Name_C= #Name_C AND Vme <> '' Group By vh.Name, vh.No, VV.Vme, RV.SF,
RV.Speed
) S GROUP BY s.RegNo, s.Name) Q`