Min Max (Date Time) And Count Data - sql-server

Using SQL Server 2014
Example Table:
| ID | Date_Time | ID_Plan |
| 1 | 2018-12-19 21:21:00.000 | A1 |
| 2 | 2018-12-19 21:22:00.000 | A1 |
| 3 | 2018-12-19 21:23:00.000 | NULL |
| 4 | 2018-12-19 21:24:00.000 | NULL |
| 5 | 2018-12-19 21:25:00.000 | A2 |
| 6 | 2018-12-19 21:26:00.000 | A2 |
| 7 | 2018-12-19 21:27:00.000 | A2 |
| 8 | 2018-12-19 21:28:00.000 | A3 |
| 9 | 2018-12-19 21:29:00.000 | A3 |
| 10 | 2018-12-19 21:30:00.000 | NULL |
| 11 | 2018-12-19 21:31:00.000 | NULL |
| 12 | 2018-12-19 21:32:00.000 | NULL |
| 13 | 2018-12-19 21:33:00.000 | A4 |
| 14 | 2018-12-19 21:34:00.000 | A4 |
| 15 | 2018-12-19 21:35:00.000 | A4 |
| 16 | 2018-12-20 21:36:00.000 | NULL |
IF OBJECT_ID('tempdb..#tb_CountFinal') IS NOT NULL
DROP TABLE #tb_CountFinal
CREATE TABLE #tb_CountFinal
(
[ID] [int] IDENTITY(1,1) NOT NULL,
Date_Time DATETIME,
ID_Plan NVARCHAR(100)
)
INSERT INTO #tb_CountFinal
SELECT '12/19/2018 21:21','A1'union all
SELECT '12/19/2018 21:22','A1'union all
SELECT '12/19/2018 21:23',NULL union all
SELECT '12/19/2018 21:24',NULL union all
SELECT '12/19/2018 21:25','A2'union all
SELECT '12/19/2018 21:26','A2'union all
SELECT '12/19/2018 21:27','A2'union all
SELECT '12/19/2018 21:28','A3'union all
SELECT '12/19/2018 21:29','A3'union all
SELECT '12/19/2018 21:30',NULL union all
SELECT '12/19/2018 21:31',NULL union all
SELECT '12/19/2018 21:32',NULL union all
SELECT '12/19/2018 21:33','A4'union all
SELECT '12/19/2018 21:34','A4'union all
SELECT '12/19/2018 21:35','A4'union all
SELECT '12/20/2018 21:36',NULL
I'm interested in a query which would output rows similar to the following:
| Start_Date | End_Date | Plan_ID | Count_PlantID |
| 12/19/2018 21:21 | 12/19/2018 21:22 | A1 | 2 |
| 12/19/2018 21:23 | 12/19/2018 21:24 | NULL | 2 |
| 12/19/2018 21:25 | 12/19/2018 21:27 | A2 | 3 |
| 12/19/2018 21:28 | 12/19/2018 21:29 | A3 | 2 |
| 12/19/2018 21:30 | 12/19/2018 21:32 | NULL | 3 |
| 12/19/2018 21:33 | 12/19/2018 21:35 | A4 | 3 |
| 12/20/2018 21:36 | 12/20/2018 21:36 | NULL | 1 |

For each NULL entries I made a key by looking at the previous starting [ID] column, then performed the Group By on that new column. Try it.
select min(Date_Time) as Start_Date, max(Date_Time) as End_Date
, min(ID_Plan) as Plan_ID, count(1) as Count_PlanID
from (
select s.*
, case when ID_Plan is null
then
cast(
(
select max([ID])
from #tb_CountFinal as x
where x.ID < s.ID and ID_Plan is not null
) as varchar(100)
)
else
ID_Plan
end as ID_Plan_Adv_Start
from #tb_CountFinal as s
) as dt
group by dt.ID_Plan_Adv_Start
order by Start_Date

Related

T-SQL: Values are grouped by month, if there is no value for a month the month should also appear and display "NULL"

i have a SQL that displays turnover, stock and other values for stores grouped by month. Logically, if there is no value for a month, the month doesn't appear. The target is that the empty month should appear and display "NULL" for the values. The empty months should range from the #FROM to the #TO parameter (201807 to 201907) in this case.
Before:
+-------+--------+----------+----------+-------+
| Store | Month | Incoming | Turnover | Stock |
+-------+--------+----------+----------+-------+
| 123 | 201810 | 5 | 4 | 1 |
| 123 | 201811 | 0 | 1 | 0 |
| 123 | 201901 | 25 | 5 | 20 |
| 123 | 201902 | 5 | 10 | 15 |
| 123 | 201903 | 8 | 9 | 14 |
| 123 | 201904 | 5 | 4 | 15 |
| 123 | 201905 | 10 | 5 | 20 |
+-------+--------+----------+----------+-------+
After:
+-------+--------+----------+----------+-------+
| Store | Month | Incoming | Turnover | Stock |
+-------+--------+----------+----------+-------+
| 123 | 201807 | NULL | NULL | NULL |
| 123 | 201808 | NULL | NULL | NULL |
| 123 | 201809 | NULL | NULL | NULL |
| 123 | 201810 | 5 | 4 | 1 |
| 123 | 201811 | 0 | 1 | 0 |
| 123 | 201812 | NULL | NULL | NULL |
| 123 | 201901 | 25 | 5 | 20 |
| 123 | 201902 | 5 | 10 | 15 |
| 123 | 201903 | 8 | 9 | 14 |
| 123 | 201904 | 5 | 4 | 15 |
| 123 | 201905 | 10 | 5 | 20 |
| 123 | 201906 | NULL | NULL | NULL |
| 123 | 201907 | NULL | NULL | NULL |
+-------+--------+----------+----------+-------+
Code Example: db<>fiddle
I have absolutely no idea how to solve this and will thank you in advance for your help! :)
You can try to use cte recursive make a calendar table, then do outer-join
;WITH CTE AS (
SELECT CAST(CAST(#FROM AS VARCHAR(10)) + '01' AS DATE) fromDt,
CAST(CAST(#TO AS VARCHAR(10)) + '01' AS DATE) toDt,
Store
FROM (SELECT DISTINCT Store FROM #Test) t1
UNION ALL
SELECT DATEADD(MONTH,1,fromDt),toDt,Store
FROM CTE
WHERE DATEADD(MONTH,1,fromDt) <= toDt
)
SELECT FORMAT(fromDt,'yyyyMM') Month,
c.Store,
t.Incoming,
t.Turnover,
t.Stock
FROM CTE c
LEFT JOIN #Test t on
c.fromDt = CAST(CAST(t.Month AS VARCHAR(10)) + '01' AS DATE)
and
c.Store = t.Store
sqlfiddle

SELECT inherit values from Parent (self-references)

I have 02 tables Rubrique and BulletinRubrique
the table Rubrique contain the following columns :
ID int not null,
Name, varchar(max) not null,
RubriqueA_ID int null,
RubriqueB_ID int null
with data for example :
+-------+---------+--------------+--------------+
| ID | Name | RubriqueA_ID | RubriqueB_ID |
+-------+---------+--------------+--------------+
| 1 | R1 | 2 | 3 |
| 2 | R2 | 1 | 2 |
| 3 | R3 | NULL | NULL |
| 4 | R4 | NULL | 6 |
| 5 | R5 | 6 | NULL |
| 6 | R6 | NULL | 1 |
+-------+---------+--------------+--------------+
the two columns RubriqueA_ID, RubriqueB_ID are the foreigns Keys for the same table Rubrique (self-referencing) and they might be NULL
For the table BulletinRubrique :
ID int not null,
EmployeID int not null,
RubriqueID int not null,
Value float not null
with data :
+-------+-----------+--------------+------------+
| ID | EmployeID | Rubrique_ID | Value |
+-------+-----------+--------------+------------+
| B1 | EMP1 | 1 | 150 |
| B1 | EMP1 | 2 | 220 |
| B1 | EMP1 | 3 | 195 |
| B1 | EMP1 | 4 | 170 |
| B1 | EMP1 | 5 | 320 |
| B1 | EMP1 | 6 | 745 |
+-------+-----------+--------------+------------+
What I am trying to do is bulding the sql query to get result as :
+-------+-----------+--------------+------------+----------+---------+
| ID | EmployeID | Rubrique_ID | Value | A_Value | B_Value |
+-------+-----------+--------------+------------+----------+---------+
| B1 | EMP1 | 1 | 150 | 220 | 195 |
| B1 | EMP1 | 2 | 220 | 150 | 220 |
| B1 | EMP1 | 3 | 195 | NULL | NULL |
| B1 | EMP1 | 4 | 170 | NULL | 745 |
| B1 | EMP1 | 5 | 320 | 745 | NULL |
| B1 | EMP1 | 6 | 745 | NULL | 150 |
+-------+-----------+--------------+------------+----------+---------+
Please help me to build this query and thanks
http://rextester.com/FIJE42564 is the working code
SELECT t2.ID, t2.EmployeID, t2.RubriqueID, t2.Value, t2.A_Value, r2.Value AS B_value FROM BulletinRubrique r2
RIGHT JOIN
(
SELECT t1.ID, t1.EmployeID, t1.RubriqueID, t1.Value, r1.VALUE AS A_VALUE, t1.B_VALUE FROM BulletinRubrique r1
RIGHT JOIN (
SELECT b.ID, b.EmployeID,b.RubriqueID, b.Value, r.RubriqueA_ID AS A_Value, r.RubriqueB_ID AS B_Value
FROM BulletinRubrique b RIGHT JOIN Rubrique r ON r.ID = b.RubriqueID ) t1
ON t1.A_Value = r1.RubriqueID
)t2
ON t2.B_Value = r2.RubriqueID
ORDER BY t2.RubriqueID
Being a fan of nested CTE, this is the way I tried solving this
WITH CTE1 as(
SELECT
BR.Id, BR.EmployeID, BR.RubriqueID, BR.value, R1.Rubriquea_Id, R2.Rubriqueb_Id
FROM
BulletinRubrique BR
LEFT JOIN
Rubrique R1 ON R1.Id = BR.RubriqueID
LEFT JOIN
Rubrique R2 ON R2.Id = BR.RubriqueID
),
CTE2 as (
SELECT
C1.Id, C1.EmployeID, C1.RubriqueID, C1.value, C2.value as A_Value, C3.value as B_Value
FROM
CTE1 C1
LEFT JOIN
CTE1 C2 ON C1.Rubriquea_Id = C2.RubriqueID
LEFT JOIN
CTE1 C3 ON C1.RubriqueB_Id = C3.RubriqueID
)
SELECT C1.Id,
C1.EmployeID,
C1.RubriqueID,
C1.value,
C1.A_Value as A_Value,
C1.B_Value as B_Value FROM CTE2 C1
ORDER BY Id

MS sql server 2014 select dynamic pivot with lag using last known value for the pivoted column

I have not found an answer yet, so this may not be possible.
I am looking for a pivot query that will replace a pivoted NULL row with the last value available for the column that was not NULL. If the First row is Null then rows are NULL until a row has a value.
Updated When CID changes the rows start as new rows. So if the first row of CID 3 is Null, then the value is null.
Here is my pivot query
DECLARE #Columns AS VARCHAR(MAX)
DECLARE #Query VARCHAR(MAX)
DECLARE #TEMP_DB VARCHAR(255)
SET #TEMP_DB = 'Demo_DataSet'
SELECT #Columns =
COALESCE(#Columns + ', ','') + QUOTENAME(AttrName)
FROM
(
SELECT DISTINCT AttrName
FROM Demo_FirstPass_Data_Raw
) AS B
ORDER BY B.AttrName
SET #Query = '
WITH PivotData AS
(
SELECT
DocID
, Customer
, Version
, CID
, AttrName
, AttrText
FROM Demo_FirstPass_Data_Raw
)
SELECT
DocID
, Customer
, Version
, CID
, ' + #Columns + '
INTO Demo_FirstPass_Data_Pivot
FROM PivotData
PIVOT
(
MAX(AttrText)
FOR AttrName
IN (' + #Columns + ')
) AS PivotResult
Where Version = Version
ORDER BY DocID, Version, CID'
DECLARE #SQL_SCRIPT VARCHAR(MAX)
SET #SQL_SCRIPT = REPLACE(#Query, '' + #TEMP_DB + '', #TEMP_DB)
EXECUTE (#SQL_SCRIPT)
My result is
DocID | Customer | Version | CID | Username | Sales_Order | Date | Description
1852 | Acme | 1 | 2 | User1 | NULL | 11/17/2010 | Product
1852 | Acme | 2 | 2 | NULL | NULL | NULL | NULL
1852 | Acme | 3 | 2 | NULL | NULL | 12/15/2010 | NULL
1852 | Acme | 4 | 2 | NULL | NULL | NULL | NULL
1852 | Acme | 5 | 2 | NULL | S-0001 | 11/17/2010 | NULL
1852 | Acme | 7 | 2 | NULL | S-0001 | NULL | NULL
1852 | Acme | 8 | 2 | NULL | NULL | 1/14/2011 | NULL
1852 | Acme | 9 | 2 | NULL | NULL | NULL | NULL
1852 | Acme | 10 | 2 | NULL | NULL | NULL | NULL
1852 | Acme | 1 | 3 | User2 | NULL | 10/10/2010 | Product
1852 | Acme | 2 | 3 | NULL | NULL | NULL | NULL
1852 | Acme | 3 | 3 | NULL | NULL | 12/15/2010 | NULL
What I am looking for is
DocID | Customer | Version | CID | Username | Sales_Order | Date | Description
1852 | Acme | 1 | 2 | User1 | NULL | 11/17/2010 | Product
1852 | Acme | 2 | 2 | User1 | NULL | 11/17/2010 | Product
1852 | Acme | 3 | 2 | User1 | NULL | 12/15/2010 | Product
1852 | Acme | 4 | 2 | User1 | NULL | 12/15/2010 | Product
1852 | Acme | 5 | 2 | User1 | S-0001 | 11/17/2010 | Product
1852 | Acme | 7 | 2 | User1 | S-0001 | 11/17/2010 | Product
1852 | Acme | 8 | 2 | User1 | S-0001 | 1/14/2011 | Product
1852 | Acme | 9 | 2 | User1 | S-0001 | 1/14/2011 | Product
1852 | Acme | 10 | 2 | User1 | S-0001 | 1/14/2011 | Product
1852 | Acme | 1 | 3 | User2 | NULL | 10/10/2010 | Product
1852 | Acme | 2 | 3 | User2 | NULL | 10/10/2010 | Product
1852 | Acme | 3 | 3 | User2 | NULL | 12/15/2010 | Product
Any help is appreciated.
For an unknown number of columns and to integrate into a dynamic pivot, one option is to generate the code for a recursive cte and use that to retain the last non null value based on your partitions like so:
declare #Columns as nvarchar(max)
declare #Query nvarchar(max)
declare #temp_db nvarchar(255)
set #temp_db = 'Demo_DataSet'
select #Columns =
coalesce(#Columns + ', ','') + quotename(AttrName)
from
(
select distinct AttrName
from Demo_FirstPass_Data_Raw
) as B
order by B.AttrName
/* generate isnull statements for columns in recursive cte */
declare #isnull nvarchar(max) = stuff((
select distinct ', isnull(t.'+quotename(d.AttrName)+',cte.'+quotename(d.AttrName)+')'
from Demo_FirstPass_Data_Raw d
order by 1
for xml path (''), type).value('(./text())[1]','nvarchar(max)')
,1,2,'')
set #Query = 'with PivotData as (
select Docid, Customer, Version, cid, AttrName, AttrText
from Demo_FirstPass_Data_Raw
)
, t as (
select
Docid, Customer, Version, cid
, ' + #Columns + '
, rn = row_number() over (partition by DocId, Customer, cid order by Version)
from PivotData
pivot(max(AttrText) for AttrName in (' + #Columns + ')) as PivotResult
)
, cte as (
select [Docid], [Customer], [Version], [cid], ' + #Columns + ', rn
from t
where version = 1
union all
select t.[Docid], t.[Customer], t.[Version], t.[cid]
, '+ #isnull + '
'+',t.rn
from t
inner join cte
on t.rn = cte.rn+1
and t.docid = cte.docid
and t.customer = cte.customer
and t.cid = cte.cid
)
select *
from cte
order by docid, customer, cid, version
'
select #query
exec sp_executesql #query
rextester demo: http://rextester.com/OQZOW62536
code generated:
with PivotData as (
select Docid, Customer, Version, cid, AttrName, AttrText
from Demo_FirstPass_Data_Raw
)
, t as (
select
Docid, Customer, Version, cid
, [Date], [Description], [Sales_Order], [Username]
, rn = row_number() over (partition by DocId, Customer, cid order by Version)
from PivotData
pivot(max(AttrText) for AttrName in ([Date], [Description], [Sales_Order], [Username])) as PivotResult
)
, cte as (
select [Docid], [Customer], [Version], [cid], [Date], [Description], [Sales_Order], [Username], rn
from t
where version = 1
union all
select t.[Docid], t.[Customer], t.[Version], t.[cid]
, isnull(t.[Date],cte.[Date]), isnull(t.[Description],cte.[Description]), isnull(t.[Sales_Order],cte.[Sales_Order]), isnull(t.[Username],cte.[Username])
,t.rn
from t
inner join cte
on t.rn = cte.rn+1
and t.docid = cte.docid
and t.customer = cte.customer
and t.cid = cte.cid
)
select *
from cte
order by docid, customer, cid, version
results:
+-------+----------+---------+-----+------------+-------------+-------------+----------+----+
| Docid | Customer | Version | cid | Date | Description | Sales_Order | Username | rn |
+-------+----------+---------+-----+------------+-------------+-------------+----------+----+
| 1852 | Acme | 1 | 2 | 2010-11-17 | Product | NULL | User1 | 1 |
| 1852 | Acme | 2 | 2 | 2010-11-17 | Product | NULL | User1 | 2 |
| 1852 | Acme | 3 | 2 | 2010-12-15 | Product | NULL | User1 | 3 |
| 1852 | Acme | 4 | 2 | 2010-12-15 | Product | NULL | User1 | 4 |
| 1852 | Acme | 5 | 2 | 2010-11-17 | Product | S-0001 | User1 | 5 |
| 1852 | Acme | 7 | 2 | 2010-11-17 | Product | S-0001 | User1 | 6 |
| 1852 | Acme | 8 | 2 | 2011-01-14 | Product | S-0001 | User1 | 7 |
| 1852 | Acme | 9 | 2 | 2011-01-14 | Product | S-0001 | User1 | 8 |
| 1852 | Acme | 10 | 2 | 2011-01-14 | Product | S-0001 | User1 | 9 |
| 1852 | Acme | 1 | 3 | 2010-10-10 | Product | NULL | User2 | 1 |
| 1852 | Acme | 2 | 3 | 2010-10-10 | Product | NULL | User2 | 2 |
| 1852 | Acme | 3 | 3 | 2010-12-15 | Product | NULL | User2 | 3 |
+-------+----------+---------+-----+------------+-------------+-------------+----------+----+

Split Time Frequency To Rows

I am trying to split a time frequency that has a start time, an end time, a frequency and a duration into separate rows. Here is some example data:
+------+------------+----------+-----------------+---------------+
| Name | Start_Time | End_Time | Frequency_Hours | Duration_Mins |
+------+------------+----------+-----------------+---------------+
| A | 08:00:00 | 18:00:00 | 2 | 2 |
| B | 00:00:00 | 23:59:59 | 1 | 5 |
| C | 00:00:00 | 23:59:59 | 4 | 15 |
+------+------------+----------+-----------------+---------------+
Can be created using the following query:
DECLARE #Tmp AS TABLE(Name VARCHAR(128)
,Start_Time VARCHAR(8)
,End_Time VARCHAR(8)
,Frequency_Hours INT
,Duration_Mins INT)
INSERT INTO #Tmp VALUES ('A','08:00:00', '18:00:00', 2,2)
,('B','00:00:00', '23:59:59', 1,5)
,('C','00:00:00', '23:59:59', 4,15)
Here is my desired output (I will then use this to drive a gantt chart visualisation):
+------+------------+----------+
| Name | Start_Time | End_Time |
+------+------------+----------+
| A | 08:00:00 | 08:02:00 |
| A | 10:00:00 | 10:02:00 |
| A | 12:00:00 | 12:02:00 |
| A | 14:00:00 | 14:02:00 |
| A | 16:00:00 | 16:02:00 |
| A | 18:00:00 | 18:02:00 |
| B | 00:00:00 | 00:05:00 |
| B | 01:00:00 | 01:05:00 |
| B | 02:00:00 | 02:05:00 |
| B | 03:00:00 | 03:05:00 |
| B | 04:00:00 | 04:05:00 |
| B | 05:00:00 | 05:05:00 |
| B | 06:00:00 | 06:05:00 |
| B | 07:00:00 | 07:05:00 |
| B | 08:00:00 | 08:05:00 |
| B | 09:00:00 | 09:05:00 |
| B | 10:00:00 | 10:05:00 |
| B | 11:00:00 | 11:05:00 |
| B | 12:00:00 | 12:05:00 |
| B | 13:00:00 | 13:05:00 |
| B | 14:00:00 | 14:05:00 |
| B | 15:00:00 | 15:05:00 |
| B | 16:00:00 | 16:05:00 |
| B | 17:00:00 | 17:05:00 |
| B | 18:00:00 | 18:05:00 |
| B | 19:00:00 | 19:05:00 |
| B | 20:00:00 | 20:05:00 |
| B | 21:00:00 | 21:05:00 |
| B | 22:00:00 | 22:05:00 |
| B | 23:00:00 | 23:05:00 |
| C | 00:00:00 | 00:15:00 |
| C | 04:00:00 | 04:15:00 |
| C | 08:00:00 | 08:15:00 |
| C | 12:00:00 | 12:15:00 |
| C | 16:00:00 | 16:15:00 |
| C | 20:00:00 | 20:15:00 |
+------+------------+----------+
I am hoping to be able to create a view out of this so I am trying to do it without cursors or other cpu intensive methods.
Any ideas?
Thanks,
Dan.
You could use a recursive cte like this
;WITH temp AS
(
SELECT t.Name, CAST(t.Start_Time AS time) AS CurrentStart_Time, dateadd(minute,t.Duration_Mins,CAST(t.Start_Time AS time)) AS CurrentEnd_Time, t.Frequency_Hours, CAST(t.End_Time AS time) AS End_Time
FROM #Tmp t
UNION ALL
SELECT t.Name, dateadd(hour,t.Frequency_Hours,t.CurrentStart_Time), dateadd(hour,t.Frequency_Hours,t.CurrentEnd_Time), t.Frequency_Hours, t.End_Time
FROM temp t
WHERE t.CurrentStart_Time < t.End_Time AND t.CurrentStart_Time < dateadd(hour,t.Frequency_Hours,t.CurrentStart_Time)
)
SELECT t.Name, t.CurrentStart_Time, t.CurrentEnd_Time
FROM temp t
ORDER BY t.Name
OPTION (MAXRECURSION 0)
Demo link: http://rextester.com/XJK25805
It can be done without RECURSIIVE CTE also.
If we create number instead of using
select distinct number master..spt_values then performance will be far better.
Like Number table can be populated from 1 to 100.
try this with various sample data,
declare #t table(Name varchar(20), Start_Time time(0),End_Time time(0)
, Frequency_Hours int,Duration_Mins int)
insert into #t VALUES
('A','08:00:00','18:00:00', 2 , 2 )
,('B','00:00:00','23:59:59', 1 , 5 )
,('C','00:00:00','23:59:59', 4 ,15 )
SELECT NAME
,dateadd(hour, n, Start_Time) Start_Time
,dateadd(minute, Duration_Mins, (dateadd(hour, n, Start_Time))) End_Time
FROM #t t
CROSS APPLY (
SELECT DISTINCT number * Frequency_Hours n
FROM master..spt_values
WHERE number >= 0
AND number <= datediff(HOUR, t.Start_Time, t.End_Time) / Frequency_Hours
) ca

Group Non-Contiguous Dates By Criteria In Column

I have a table with start and end dates for team consultations with customers.
I need to merge certain consultations based on a number of days specified in another column (sometimes the consultations may overlap, sometimes they are contiguous, sometimes they arent), Team and Type.
Some example data is as follows:
DECLARE #TempTable TABLE([CUSTOMER_ID] INT
,[TEAM] VARCHAR(1)
,[TYPE] VARCHAR(1)
,[START_DATE] DATETIME
,[END_DATE] DATETIME
,[GROUP_DAYS_CRITERIA] INT)
INSERT INTO #TempTable VALUES (1,'A','A','2013-08-07','2013-12-31',28)
,(2,'B','A','2015-05-15','2015-05-28',28)
,(2,'B','A','2015-05-15','2016-05-12',28)
,(2,'B','A','2015-05-28','2015-05-28',28)
,(3,'C','A','2013-05-27','2014-07-23',28)
,(3,'C','A','2015-01-12','2015-05-28',28)
,(3,'B','A','2015-01-12','2015-05-28',28)
,(3,'C','A','2015-05-28','2015-05-28',28)
,(3,'C','A','2015-05-28','2015-12-17',28)
,(4,'A','B','2013-07-09','2014-04-21',7)
,(4,'A','B','2014-04-29','2014-08-01',7)
Which looks like this:
+-------------+------+------+------------+------------+---------------------+
| CUSTOMER_ID | TEAM | TYPE | START_DATE | END_DATE | GROUP_DAYS_CRITERIA |
+-------------+------+------+------------+------------+---------------------+
| 1 | A | A | 07/08/2013 | 31/12/2013 | 28 |
| 2 | B | A | 15/05/2015 | 28/05/2015 | 28 |
| 2 | B | A | 15/05/2015 | 12/05/2016 | 28 |
| 2 | B | A | 28/05/2015 | 28/05/2015 | 28 |
| 3 | C | A | 27/05/2013 | 23/07/2014 | 28 |
| 3 | C | A | 12/01/2015 | 28/05/2015 | 28 |
| 3 | B | A | 12/01/2015 | 28/05/2015 | 28 |
| 3 | C | A | 28/05/2015 | 28/05/2015 | 28 |
| 3 | C | A | 28/05/2015 | 17/12/2015 | 28 |
| 4 | A | B | 09/07/2013 | 21/04/2014 | 7 |
| 4 | A | B | 29/04/2014 | 01/08/2014 | 7 |
+-------------+------+------+------------+------------+---------------------+
My desired output is as follows:
+-------------+------+------+------------+------------+---------------------+
| CUSTOMER_ID | TEAM | TYPE | START_DATE | END_DATE | GROUP_DAYS_CRITERIA |
+-------------+------+------+------------+------------+---------------------+
| 1 | A | A | 07/08/2013 | 31/12/2013 | 28 |
| 2 | B | A | 15/05/2015 | 12/05/2016 | 28 |
| 3 | C | A | 27/05/2013 | 23/07/2014 | 28 |
| 3 | C | A | 12/01/2015 | 17/12/2015 | 28 |
| 3 | B | A | 12/01/2015 | 28/05/2015 | 28 |
| 4 | A | B | 09/07/2013 | 21/04/2014 | 7 |
| 4 | A | B | 29/04/2014 | 01/08/2014 | 7 |
+-------------+------+------+------------+------------+---------------------+
I am struggling to do this at all, let alone with any efficiency! Any ideas / code will be greatly received.
Server version is MS SQL Server 2014
Thanks,
Dan
If I am understanding your question correctly, we want to return rows only when a second, third, etc consultation has not occurred within group_days_criteria number of days after the previous consultation end date.
We can get the previous consultation end date and eliminate rows (since we are not concerned with the number of consultations) where a consultation occurred for the same customer by the same team and of the same consultation type within our date range.
DECLARE #TempTable TABLE([CUSTOMER_ID] INT
,[TEAM] VARCHAR(1)
,[TYPE] VARCHAR(1)
,[START_DATE] DATETIME
,[END_DATE] DATETIME
,[GROUP_DAYS_CRITERIA] INT)
INSERT INTO #TempTable VALUES (1,'A','A','2013-08-07','2013-12-31',28)
,(2,'B','A','2015-05-15','2015-05-28',28)
,(2,'B','A','2015-05-15','2016-05-12',28)
,(2,'B','A','2015-05-28','2015-05-28',28)
,(3,'C','A','2013-05-27','2014-07-23',28)
,(3,'C','A','2015-01-12','2015-05-28',28)
,(3,'B','A','2015-01-12','2015-05-28',28)
,(3,'C','A','2015-05-28','2015-05-28',28)
,(3,'C','A','2015-05-28','2015-12-17',28)
,(4,'A','B','2013-07-09','2014-04-21',7)
,(4,'A','B','2014-04-29','2014-08-01',7)
;with prep as (
select Customer_ID,
Team,
[Type],
[Start_Date],
[End_Date],
Group_Days_Criteria,
ROW_NUMBER() over (partition by customer_id, team, [type] order by [start_date] asc, [end_date] desc) as rn, -- earliest start date with latest end date
lag([End_Date] + Group_Days_Criteria, 1, 0) over (partition by customer_id, team, [type] order by [start_date] asc, [end_date] desc) as PreviousEndDate -- previous end date +
from #TempTable
)
select p.Customer_Id,
p.[Team],
p.[Type],
p.[Start_Date],
p.[End_Date],
p.Group_Days_Criteria
from prep p
where p.rn = 1
or (p.rn != 1 and p.[Start_date] > p.PreviousEndDate)
order by p.Customer_Id, p.[Team], p.[Start_Date], p.[Type]
This returned the desired result set.

Resources