Question
Finding Product Switches on Account Between Dates
I am working on a problem were we have a table that holds id, product code , accountid , date
CREATE TABLE AccountBalanceAndProduct
(
[ID] [int] NOT NULL IDENTITY(1, 1),
[EffectiveDate] [date] NULL,
[AccountID] [varchar] (20) NULL,
[Product] [varchar] (20)
)
INSERT INTO AccountBalanceAndProduct (EffectiveDate, Accountid, Product)
VALUES
('2024-07-10', 'Acc1', 'ABA'),
('2024-07-11', 'Acc1', 'ABA'),
('2024-07-12', 'Acc1', 'ABB'),
('2024-07-12', 'Acc1', 'ABA'),
('2024-07-13', 'Acc1', 'ABB'),
('2024-07-14', 'Acc1', 'ABA'),
('2024-07-15', 'Acc1', 'ABC'),
('2024-07-16', 'Acc1', 'ABC'),
('2024-07-17', 'Acc1', 'ABA'),
('2024-07-10', 'Acc2', 'ABA'),
('2024-07-11', 'Acc2', 'ABA'),
('2024-07-12', 'Acc2', 'ABB'),
('2024-07-13', 'Acc2', 'ABB'),
('2024-07-14', 'Acc2', 'ABA'),
('2024-07-15', 'Acc2', 'ABC'),
('2024-07-16', 'Acc2', 'ABC'),
('2024-07-17', 'Acc2', 'ABA')
What I am trying to work out is when an account changes to a new product with To and From dates of the change along with To and From Product codes
I have wrote the below code but it does not take into account if an account changes from one product to another then back again. I am struggling to find something online to see how this can be done.
Records are added daily to this table with the current product and a account and can hold two at the same time briefly while a manual operations process removes the old product- normally this happens before the new product is added.
;WITH ProductSwitch AS
(
SELECT
a.id,
a.Accountid,
a.Product,
a.EffectiveDate[DateSwitchedTo],
ROW_NUMBER() OVER (PARTITION BY AccountID ORDER BY a.id ASC) [RowNumber]
FROM
(SELECT
MIN(bal.ID) [id],
bal.AccountId,
bal.Product,
MIN(bal.EffectiveDate) [EffectiveDate]
FROM
AccountBalanceAndProduct bal
WHERE
1 = 1
GROUP BY
bal.Product, bal.Accountid) a
)
SELECT
a.AccountID,
a.Product[ProductFrom],
a.DateSwitchedTo[FromDate],
b.Product[ProductTo],
b.DateSwitchedTo[ToDate],
b.RowNumber - 1 [TotalNumberOfSwitchesAtTimeOfSwitch]
FROM
(SELECT
asw.AccountID,
asw.Product,
asw.DateSwitchedTo,
asw.RowNumber
FROM
ProductSwitch asw) a
JOIN
(SELECT
asw.AccountID,
asw.Product,
asw.DateSwitchedTo,
asw.RowNumber
FROM
ProductSwitch asw
WHERE
asw.RowNumber > 1) b ON a.RowNumber = b.RowNumber - 1
AND a.AccountID = b.AccountID
I have created a fiddle https://dbfiddle.uk/8Y7ybsKp
This populates the table with dummy data and shows by current results along with expected result set
I hope that makes sense.
Expected results:
CREATE TABLE ExpectedResults
(
AccountID [varchar](20) NULL,
ProductFrom [varchar](20) NULL,
FromDate [date] NULL,
ProductTo [varchar](20) NULL,
ToDate [date] NULL,
TotalNumberOfSwitchesAtTimeOfSwitch int null
)
INSERT INTO ExpectedResults (AccountID, ProductFrom, FromDate,
ProductTo, ToDate, TotalNumberOfSwitchesAtTimeOfSwitch)
VALUES
('Acc1', 'ABA' ,'2024-07-10' ,'ABB' ,'2024-07-12', 1),
('Acc1', 'ABB' ,'2024-07-12' ,'ABA' ,'2024-07-14', 2),
('Acc1', 'ABA' ,'2024-07-14' ,'ABB' ,'2024-07-16', 3),
('Acc1', 'ABA' ,'2024-07-16' ,'ABC' ,'2024-07-17', 4),
('Acc2', 'ABA' ,'2024-07-10' ,'ABB' ,'2024-07-12', 1),
('Acc2', 'ABB' ,'2024-07-12' ,'ABA' ,'2024-07-14', 2),
('Acc2', 'ABA' ,'2024-07-14' ,'ABB' ,'2024-07-16', 3),
('Acc2', 'ABA' ,'2024-07-16' ,'ABC' ,'2024-07-17', 4)