Although this code is working, it isn't very efficient--making heavy use of temp tables, which I'd rather consolidate. The create sumtest table and the insert statements that write to it are included for anyone interested in working with the sample data.
CREATE TABLE SumTest(
POSDate datetime NULL,
debit money NULL,
credit money NULL,
RollingBalance money NULL,
expires datetime NULL,
ExpiringDebitBalance_2013 money,
ExpiringDebitBalance_2014 money
);
-- mimic actual sales transactions
insert into sumtest (POSDate,debit,credit,expires) values ('Jan 5 2013 12:00AM','670.00','22.00','Dec 31 2014 12:00AM');
insert into sumtest (POSDate,debit,credit,expires) values ('Jan 6 2013 12:00AM','821.00','0.00','Dec 31 2014 12:00AM');
insert into sumtest (POSDate,debit,credit,expires) values ('Mar 8 2013 12:00AM','62.00','700.00','Dec 31 2014 12:00AM');
insert into sumtest (POSDate,debit,credit,expires) values ('Mar 11 2013 12:00AM','78.00','29.00','Dec 31 2014 12:00AM');
insert into sumtest (POSDate,debit,credit,expires) values ('Mar 11 2013 12:00AM','900.00','87.00','Dec 31 2014 12:00AM');
insert into sumtest (POSDate,debit,credit,expires) values ('Apr 16 2013 12:00AM','0.00','440.00',NULL);
insert into sumtest (POSDate,debit,credit,expires) values ('Aug 18 2013 12:00AM','0.00','50.00',NULL);
insert into sumtest (POSDate,debit,credit,expires) values ('Aug 19 2013 12:00AM','470.00','200.00','Dec 31 2014 12:00AM');
insert into sumtest (POSDate,debit,credit,expires) values ('Dec 31 2012 12:00AM','1000.00','200.00','Dec 31 2013 12:00AM');
insert into sumtest (POSDate,debit,credit,expires) values ('Dec 22 2013 12:00AM','200.00','0.00','Dec 31 2014 12:00AM');
insert into sumtest (POSDate,debit,credit,expires) values ('Dec 20 2013 12:00AM','500.00','0.00','Dec 31 2014 12:00AM');
insert into sumtest (POSDate,debit,credit,expires) values ('Nov 10 2012 12:00AM','200.00','0.00','Dec 31 2013 12:00AM');
insert into sumtest (POSDate,debit,credit,expires) values ('Nov 11 2012 12:00AM','150.00','0.00','Dec 31 2013 12:00AM');
insert into sumtest (POSDate,debit,credit,expires) values ('Nov 15 2012 12:00AM','0.00','100.00',NULL);
-- // ---------- REAL CODE BEGINS -------------------------- // --
create table #work
(
POSYear int NULL,
POSMonth int NULL,
debit money NULL,
credit money NULL,
RollingBalance money NULL,
expires datetime
)
-- start with ditching the time
insert into #work
(POSYear,POSMonth,debit,credit,expires)
select datepart(Year, POSDate) as POSYear
,datepart(Month, POSDate) as POSMonth
,debit
,credit
,expires
from sumtest
-- dump an ordered set by year,month with a rolling balance of all points/redemptions
;with distilled as
(select POSYear,
POSMonth,
TotalDebit = sum(debit),
TotalCredit = sum(credit),
expires
from #work
group by POSYear,POSMonth,expires
)
select POSYear,
POSMonth,
TotalDebit,
TotalCredit,
RollingBalance = sum(totaldebit + (totalcredit)*-1) over ( order by POSYear, POSMonth),
expires
into #work2
from distilled
order by POSYear,POSMonth,TotalDebit,TotalCredit
-- filter out credits lines that dont have an expiration date
-- Note: I would rather not do this--if there is a better way
-- to sum up by yyyy,mm here to consolidate to
-- single rows please advise.
select x.POSYear,
x.POSMonth,
sum(x.TotalDebit) as TotalDebit,
sum(x.TotalCredit) as TotalCredit,
x.RollingBalance,
EXPYear = datepart(Year, y.expires),
EXPMonth = datepart(Month, y.expires)
into #work3
from #work2 x
inner join #work2 y on x.posyear = y.posyear
and x.posmonth = y.posmonth
where y.expires is not null
group by x.posyear,x.posmonth,x.rollingbalance,y.expires
order by posyear,posmonth
-- add back in lines that are single credits, w/o debits
-- Note: I like this even less! :-\
INSERT INTO #work3
(POSYear,POSMonth,TotalDebit,TotalCredit,RollingBalance,EXPYear,EXPMonth)
select
POSYear,
POSMonth,
TotalDebit,
TotalCredit,
RollingBalance,
case
when expires is null then (POSYear + 1)
end as EXPYear,
case
when expires is null then 12
end as EXPMonth
from #work2
where (POSYear + POSMonth) NOT IN (
select POSYear + POSMonth
from #work3);
There doesn't appear to be a need for #work which can be replaced with
;with distilled as
(
select POSYear,
POSMonth,
TotalDebit = sum(debit),
TotalCredit = sum(credit),
expires
from (
select datepart(Year, POSDate) as POSYear
,datepart(Month, POSDate) as POSMonth
,debit
,credit
,expires
from sumtest
)
group by POSYear,POSMonth,expires
)
select POSYear,
POSMonth,
TotalDebit,
TotalCredit,
RollingBalance = sum(totaldebit + (totalcredit)*-1) over ( order by POSYear, POSMonth),
expires
into #work2
from distilled
I think the last two queries can be simplified to
select x.POSYear,
x.POSMonth,
sum(case when expires is null then 0 else x.TotalDebit end) as TotalDebit,
sum(case when expires is null then 0 else x.TotalCredit end) as TotalCredit,
x.RollingBalance,
EXPYear = case when expires is null then (POSYear + 1)
else datepart(Year, y.expires)
end,
EXPMonth = case when expires is null then 12
else datepart(Month, y.expires)
end
into #work3
from #work2 x
inner join #work2 y on x.posyear = y.posyear
and x.posmonth = y.posmonth
group by x.posyear,x.posmonth,x.rollingbalance,y.expires
You also don't seem to really need to be ordering anything
OK, here's the refined version--no temp tables.
SELECT
POSYear
, POSMonth
, TotalDebit AS TotalEarned
, TotalCredit AS TotalRedeemed
, RollingBalance
, EXPYear
, EXPMonth
, case
when EXPYear = 2013 then RollingBalance
else 0
end as EXPRollingBal_2013
, case
when prevEXPYear <> EXPYear then lag(RollingBalance,1) over (ORDER BY POSYear ,POSMonth) - TotalCredit
end as "EXPCarryForwardBal" -- // Note: This only works for the first instance AFTER then new year. Wrong!
, case
-- when EXPYear = 2014 then RollingBalance // Note: This is WRONG, zero it out for now.
when EXPYear = 2014 then 0.00
else 0
end as EXPRollingBal_2014
INTO #baseExpiring
FROM (
SELECT
POSYear
, POSMonth
, TotalDebit
, TotalCredit
, sum(TotalDebit - TotalCredit) over (ORDER BY POSYear ,POSMonth) AS RollingBalance
, EXPYear
, EXPMonth
, lag(EXPYear,1) over (ORDER BY POSYear ,POSMonth) as prevEXPYear
FROM (
SELECT
year(posdate) AS POSYear
, month(posdate) AS POSMonth
, sum(debit) AS TotalDebit
, sum(credit) AS TotalCredit
, CASE
WHEN expires IS NULL THEN year(posdate) + 1
ELSE year(expires)
END AS EXPYear
, CASE
WHEN expires IS NULL THEN 12
ELSE month(expires)
END AS EXPMonth
FROM SumTest
GROUP BY
year(posdate)
, month(posdate)
, CASE
WHEN expires IS NULL THEN year(posdate) + 1
ELSE year(expires)
END
, CASE WHEN expires IS NULL THEN 12
ELSE month(expires)
END
) as dataset1 -- // resolve line consolidation when there's a standalone redempton when summed, leaving 2 distinct yyyy,mm rows.
) as dataset2 -- // broader resolution of rolling balance w/windowing.
;
Related
I have a table with a list of individuals that have a effective date and a termination date.
example Person 1, 20171201, 20180601
For each record, I need to output a list of years and months they were "active" between the two dates.
So the output would look like
Data Output
This is in SQL Server 2016
Any help would be appreciated!
Just because I did not see it offered. Here is yet another approach which uses an ad-hoc calendar table
Note the base date of 2000-01-01 and 10,000 days ... expand or contract if needed
Example
Declare #YourTable table (Person int,startdate date, enddate date)
Insert Into #YourTable values
(1,'20171201','20180601')
Select Distinct
A.Person
,ActiveYear = year(D)
,ActiveMonth = month(D)
From #YourTable A
Join (
Select Top 10000 D=DateAdd(DAY,-1+Row_Number() Over (Order By (Select Null)),'2000-01-01')
From master..spt_values n1,master..spt_values n2
) B on D between startdate and enddate
Returns
Person ActiveYear ActiveMonth
1 2017 12
1 2018 1
1 2018 2
1 2018 3
1 2018 4
1 2018 5
1 2018 6
Based on info you've provided, I did a little guessing. Perhaps a recursive CTE will help:
DECLARE #tab TABLE (Person INT, EffectiveDate DATE, TerminationDate DATE)
INSERT #tab VALUES
(1, '2017-12-01', '2018-05-31'),
(2, '2017-10-01', '2018-01-01'),
(3, '2018-02-01', '2018-12-01')
;WITH t AS (
SELECT Person, EffectiveDate AS Dt
FROM #tab
UNION ALL
SELECT Person, DATEADD(mm,1,Dt)
FROM t
WHERE t.Dt < (SELECT DATEADD(mm,-1,TerminationDate) FROM #tab tt WHERE tt.Person = t.Person)
)
SELECT *
FROM t
ORDER BY Dt
Then take the DATEPART()
SELECT t.Person
, t.Dt
, DATEPART(yyyy, t.Dt) ActiveYear
, DATEPART(mm, t.Dt) ActiveMonth
FROM t
ORDER BY Dt
Welcome to stackoverflow! For better help it's good to include DDL easily consumable sample data that we can use to quickly re-create what you are doing and provide a solution. Note this sample data:
DECLARE #yourtable TABLE(person VARCHAR(20), date1 DATE, date2 DATE)
INSERT #yourtable (person, date1, date2)
VALUES ('Person1','20171201', '20180601'), ('Person2','20171001', '20180101'),
('Person3','20180101', '20180301');
SELECT t.* FROM #yourtable AS t;
Returns:
person date1 date2
-------------------- ---------- ----------
Person1 2017-12-01 2018-06-01
Person2 2017-10-01 2018-01-01
Person3 2018-01-01 2018-03-01
(I added a couple rows). Here's my solution:
DECLARE #yourtable TABLE(person VARCHAR(20), date1 DATE, date2 DATE)
INSERT #yourtable (person, date1, date2)
VALUES ('Person1','20171201', '20180601'), ('Person2','20171001', '20180101'),
('Person3','20180101', '20180301');
SELECT
Person = t.person,
ActiveYear = YEAR(st.DT),
ActiveMonth = MONTH(st.Dt)
FROM #yourtable AS t
CROSS APPLY
(
SELECT TOP (DATEDIFF(MONTH,t.date1,t.date2)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS a(x)
CROSS JOIN (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS b(x)
) AS iTally(N)
CROSS APPLY (VALUES(DATEADD(MONTH, iTally.N-1, t.date1))) AS st(Dt);
Which returns:
Person ActiveYear ActiveMonth
-------------------- ----------- -----------
Person1 2017 12
Person1 2018 1
Person1 2018 2
Person1 2018 3
Person1 2018 4
Person1 2018 5
Person2 2017 10
Person2 2017 11
Person2 2017 12
Person3 2018 1
Person3 2018 2
Let me know if you have questions.
I have a series something like this:
Month J F M A M J J A S O N D
Status 1 0 0 1 0 1 0 0 1 1 1 1
Using t-SQL, I am trying to capture the month corresponding to the first 1 in the last group of 1s, i.e., September in this example.
Here is the code I'm using:
IF OBJECT_ID('tempdb..#Temp1') IS NOT NULL DROP TABLE #Temp1
;WITH PARTITIONED1 AS
(SELECT , t0.ID
, t0.Year_Month
, t0.Status
, LAST_VALUE(t0.Year_Month) OVER (PARTITION BY t0.ID ORDER BY t0.Year_Month) AS D_YM
, ROW_NUMBER() OVER (PARTITION BY t0.ID ORDER BY t0.Year_Month) AS rn1
FROM #Temp0 t0
However, this just returns the first occurence of a 1; January here.
I really can't figure this one out, so any help would be very much appreciated.
Carefull with
although the ordering is performed in a previous stage
The previous sorting does not guarantee the later processing!
Try something like this. It is a very simple approach where you rely on gapless IDs:
DECLARE #tbl TABLE(ID INT IDENTITY,Mnth VARCHAR(100),[Status] TINYINT);
INSERT INTO #tbl VALUES
('J',1)
,('F',0)
,('M',0)
,('A',1)
,('M',0)
,('J',1)
,('J',0)
,('A',0)
,('S',1)
,('O',1)
,('N',1)
,('D',1);
SELECT a.*
FROM #tbl AS a
WHERE a.ID=(SELECT MAX(b.ID)+1 FROM #tbl AS b WHERE b.[Status]=0)
this can also be used :
select top 1 Month from table t where Status=1
and not exists
(select id from table t1 where stat=0 and t1.id>t.id)
order by t.id
I might have overcomplicated this but not knowing the table structure I put the below together:
IF OBJECT_ID('tempdb..#Temp1') IS NOT NULL DROP TABLE #Temp1
CREATE TABLE #Temp1
(
Jan int,
Feb int,
Mar int,
Apr int,
May int,
June int,
July int ,
Aug int,
Sep int,
Oct int,
Nov int,
Dec int
)
insert into #temp1
select
1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1
IF OBJECT_ID('tempdb..#monthTranslate') IS NOT NULL DROP TABLE #monthTranslate
create table #monthTranslate
(
MonthValue varchar(50),
MonthInt int
)
insert into #monthTranslate
select 'Jan',1
union all select 'Feb',2
union all select 'Mar',3
union all select 'Apr',4
union all select 'May',5
union all select 'June',6
union all select 'July',7
union all select 'Aug',8
union all select 'Sep',9
union all select 'OCt',10
union all select 'Nov',11
union all select 'Dec',12
--find the max month w\ 0 and add 1... becareful on null, it might return January incorrectly. I'd check for that in a a case statement
select max(b.MonthInt)+1
from
(
select
MonthPassVal, months , t.MonthInt
from
(
select Jan, Feb, Mar, Apr, May, June, July, Aug, Sep, Oct, Nov, Dec
from #temp1
) as r
Unpivot
(
MonthPassVal for Months
in (Jan, Feb, Mar, Apr, May, June, July, Aug, Sep, Oct, Nov, Dec)
) as u
inner join #monthTranslate t
on t.MonthValue = months
) as b
where
MonthPassVal=0
I have a question on SQL 2008 which is probably quite easy but I can't see the woods for the trees now.
I am trying to produce a sql based report detailing the last six months of helpdesk issue stats, per application, per office, per month which I then take into ssrs to apply prettiness :o)
Anyway - I have my script, which is fine on a month by month basis, for example;
SELECT distinct t.name_1 'Application',
(select distinct name from location where location_ref = c.location_ref) as office,
Count (t.name_1) as [Call Count],
datename(month, dateadd(month,-2,getdate()))+' '+datename(year, dateadd(month,-2,getdate())) as [Report Month]
FROM call_logging C
Inner Join problem_type t On t.ref_composite = c.ref_composite
AND c.resolve_time between onvert(datetime,convert(varchar,month(dateadd(m,-2,getdate()))) + '/01/' + convert(varchar,year(dateadd(m,-2,getdate()))))
and convert(datetime,convert(varchar,month(dateadd(m,-1,getdate()))) + '/01/' + convert(varchar,year(getdate())))
and c.resolve_group in ('48', '60')
which brings back all of May's issues.
The problem is that t.name_1 (the application in which the issue is for) is dynamic and the list grows or shrinks every month.
I basically need a layout of
APPLICATION OFFICE COUNT JUNE MAY APRIL MARCH FEB JAN
WORD LONDON 20 1 1 2 5 10 1
WORD PARIS 10 2 3 1 2 0 3
EXCEL MADRID 05 0 0 3 2 0 0
etc (if that makes sense on this layout!)
I've gone down the 6 separate reports road but it just doesn't look very nice in ssrs. I've thought about #tmptables but they don't like inserting distinct rows.
SELECT [C].[name_1] AS [APPLICATION]
,COUNT([name_1]) AS [CALL COUNT]
,[l].[location_ref]
,[dbo].[ufn_GetDateTime_CalenderYearMonth]([resolve_time]) AS [StartCalenderYearMonth]
FROM [call_logging] [C] INNER JOIN [problem_type] [t]
ON [t].[ref_composite] = [c].[ref_composite]
AND [c].[resolve_group] IN ('48', '60')
INNER JOIN [location] [l] ON [c].[location_ref] = [l].[location_ref]
WHERE [C].[resolve_time] BETWEEN '2011-01-01' AND GETDATE()
GROUP BY [C].[name_1], [l].[location_ref], [dbo].[ufn_GetDateTime_CalenderYearMonth]([resolve_time])
And the code for ufn_GetDateTime_CalenderYearMonth is:
CREATE FUNCTION [dbo].[ufn_GetDateTime_CalenderYearMonth] (#DateTime datetime)
RETURNS varchar(20)
AS
BEGIN
declare #dateString varchar(20)
declare #yearString varchar(10)
declare #monthString varchar(10)
set #yearString = cast( DATEPART(year, #DateTime) as varchar(10))
if(DATEPART(month, #DateTime) < 10)
set #monthString = '0' + cast( DATEPART(month, #DateTime) as varchar(5) )
else
set #monthString = cast( DATEPART(month, #DateTime) as varchar(5) )
set #dateString = #yearString + '-' + #monthString
RETURN (#dateString)
END
You just slap the resultset in a matrix and group everything by [StartCalenderYearMonth] and it will show numbers for each month from 1st of Jan 2011 till now..
I'm surprised this hasn't come up yet.
In T-SQL, I need to find the intervals (defined by startDateTime and endDateTime) that overlap with daily interval (say 9am-5pm).
For example, with table:
CREATE TABLE [dbo].[Interval](
[startDateTime] [datetime] NOT NULL,
[endDateTime] [datetime] NOT NULL
)
Solution would be the procedure that returns only overlapping intervals:
CREATE PROCEDURE FindIntervals
-- Add the parameters for the stored procedure here
#from varchar(5) = '9:00',
#to varchar(5) = '17:00'
AS
BEGIN
select * from Interval
where ...
END
GO
EDIT:
Example intervals:
Sep 7 2011 8:00 AM - Sep 7 2011 8:30 PM
Sep 7 2011 11:00 AM - Sep 7 2011 1:00 PM
Sep 7 2011 1:00 PM - Sep 7 2011 6:00 PM
Sep 9 2011 8:00 AM - Sep 9 2011 8:30 PM
Sep 9 2011 11:00 AM - Sep 9 2011 1:00 PM
Sep 9 2011 1:00 PM - Sep 9 2011 6:00 PM
So, for given interval "nine to five", 2, 3, 5 and 6 should be returned, as they overlap the given input.
But,
Sep 9 2011 8:00 AM - Sep 10 2011 8:30 PM
also fits, because it includes entire day.
Please, I need help with matching string and datetime values in T-SQL, not abstract "less then"/"greater then" solutions.
declare #Interval table
(
startDateTime datetime,
endDateTime datetime
)
insert into #Interval values
('2011-09-07T08:00:00', '2011-09-07T08:30:00'),
('2011-09-07T11:00:00', '2011-09-07T13:00:00'),
('2011-09-07T13:00:00', '2011-09-07T18:00:00'),
('2011-09-09T08:00:00', '2011-09-09T08:30:00'),
('2011-09-09T11:00:00', '2011-09-09T13:00:00'),
('2011-09-09T13:00:00', '2011-09-09T18:00:00'),
('2011-09-09T08:00:00', '2011-09-10T08:30:00')
declare #from varchar(5) = '09:00'
declare #to varchar(5) = '17:00'
;with L(MinDate, MaxDate) as
(
select dateadd(day, datediff(day, 0, min(startDateTime)), 0),
dateadd(day, datediff(day, 0, max(endDateTime)), 0)
from #Interval
),
D(fromTime, endTime) as
(
select dateadd(day, Number.number, L.MinDate)+cast(#from as datetime),
dateadd(day, Number.number, L.MinDate)+cast(#to as datetime)
from L
inner join master..spt_values as Number
on Number.number <= datediff(day, L.MinDate, L.MaxDate)
where Number.type = 'P'
)
select I.startDateTime,
I.endDateTime
from #Interval as I
where exists (select *
from D
where I.startDateTime < D.endTime and
I.endDateTime > D.fromTime)
Result:
startDateTime endDateTime
----------------------- -----------------------
2011-09-07 11:00:00.000 2011-09-07 13:00:00.000
2011-09-07 13:00:00.000 2011-09-07 18:00:00.000
2011-09-09 11:00:00.000 2011-09-09 13:00:00.000
2011-09-09 13:00:00.000 2011-09-09 18:00:00.000
2011-09-09 08:00:00.000 2011-09-10 08:30:00.000
If you expect to have a date range of more than 2048 days you need to replace master..spt_values with a numbers table. Make sure the numbers table starts with 0.
SQL Server 2008 version
;with L(MinDate, MaxDate) as
(
select cast(min(startDateTime) as date),
cast(max(endDateTime) as date)
from #Interval
),
D(fromTime, endTime) as
(
select dateadd(day, Number.number, L.MinDate)+cast(#from as datetime),
dateadd(day, Number.number, L.MinDate)+cast(#to as datetime)
from L
inner join master..spt_values as Number
on Number.number <= datediff(day, L.MinDate, L.MaxDate)
where Number.type = 'P'
)
select I.startDateTime,
I.endDateTime
from #Interval as I
where exists (select *
from D
where I.startDateTime < D.endTime and
I.endDateTime > D.fromTime)
I am stuck with generating a new column. The table has three columns(C_ID, C_rank, Date).
C_ID C_ Rank NewColumn(Cycle) Date
42 A 1 October 14, 2010
42 B 1 October 26, 2010
42 A 2 February 16, 2011
43 A 1 December 17, 2010
44 A 1 July 28, 2010
44 B 1 August 10, 2010
44 A 2 January 11, 2011
44 B 2 January 28, 2011
45 A 1 July 30, 2010
45 B 1 August 9, 2010
45 B 1 September 24, 2010
45 A 2 April 5, 2011
45 B 2 April 26, 2011
I want to generate one more column called Cycle in such a way that for each C_ID, it should generate the number start from one and increment the number from next C_rank = 'A' (a shown above).
I tried using row_number, but no luck.
Maybe some loop option till next C_Rank = 'A' works.
How can this be done?
You should be able to get this done using ROW_NUMBER() and PARTITION BY
;WITH YourDataCTE AS
(
SELECT
C_ID, C_Rank, Date,
ROW_NUMBER() OVER(PARTITION BY C_ID,C_Rank ORDER BY Date DESC) AS 'Cycle'
FROM
dbo.YourTable
)
SELECT *
FROM YourDataCTE
Does that do what you're looking for??
The PARTITION BY C_ID,C_Rank will cause the ROW_NUMBER to start at 1 again for each different value of C_ID,C_Rank - I didn't know what ORDER BY clause within a single partition (a single value of C_ID,C_Rank) you're looking for and just guessed it might be Date DESC (newest date first).
You could count the number of previous A's in a subquery:
select *
, (
select count(*)
from #YourTable yt2
where yt2.C_ID = yt1.C_ID
and yt2.C_Rank = 'A'
and yt2.Date <= yt1.Date
) as Cycle
from #YourTable yt1
order by
C_ID, Date
Example at ODATA.
Do a self join for all records with the same C_ID, a previous date, and a C_Rank='A' and count them.
select t1.C_ID, t1.C_Rank, count(t2.C_Rank) Cycle, t1.Date
from MyTable t1
left join MyTable t2 on t1.C_ID=t2.C_ID
and t2.Date<=t1.Date
and t2.C_Rank='A'
group by t1.C_ID, t1.C_Rank, t1.Date
order by t1.C_ID, t1.Date
Below code fulfill the requirement:
create table #Temp_Table
(
C_ID int
, C_Rank char(1)
, Date datetime
, NewColumn int
)
insert into #Temp_Table
(
C_ID
, C_Rank
, Date
)
select 42, ‘A’, ’10/14/2010′
union all
select 42, ‘B’, ’10/26/2010′
union all
select 42, ‘B’, ’10/14/2010′
union all
select 42, ‘C’, ’10/26/2010′
union all
select 42, ‘A’,’02/16/2011′
union all
select 43, ‘A’, ’12/17/2010′
union all
select 44, ‘A’, ’07/28/2010′
union all
select 44, ‘B’, ’08/10/2010′
union all
select 44, ‘A’, ’01/11/2011′
union all
select 44, ‘B’, ’01/28/2011′
union all
select 44, ‘C’, ’10/14/2010′
union all
select 44, ‘D’, ’10/26/2010′
Select ‘Original Data’ Comment
,*
from #Temp_Table
/*
This would be Actual Script to get the New ID based on information you provided
*/
Declare #Count int
,#C_ID int
,#C_Rank char(1)
,#total_Count int
,#Count_Partition int
,#Previous_ID int
Declare #Table Table (ID int IDENTITY(1,1), C_ID int, C_Rank char(1), Date datetime, NewColumn int )
Set #Count = 1
Set #Count_Partition = 0
insert into #Table
Select *
from #Temp_Table
Select #total_Count = ISNULL(MAX(ID),0)
from #Table
While #Count < = #total_Count
Begin
Select #C_ID = C_ID
,#C_Rank = C_Rank
From #Table
Where ID = #Count
If #Count = 1
Set #Previous_ID = #C_ID
If #Previous_ID != #C_ID
Set #Count_Partition = 1
Else If #C_Rank = 'A'
Set #Count_Partition = #Count_Partition + 1
update #Table
Set NewColumn = #Count_Partition
Where ID = #Count
Set #Previous_ID = #C_ID
Set #Count = #Count + 1
End
Select C_ID
, C_Rank
, [Date]
, NewColumn
from #Table
–Drop table #Temp_Table