April 17, 2009 at 8:06 am
I have a table that contains account balance for every customer each day. I need to count the number of (consecutive) days for which the balance is not changed.
IF object_id('tempdb..#Balance') IS NOT NULL
drop table #Balance
GO
CREATE TABLE #Balance(
CUSTOMER_NO int
,CURRENT_BALANCE numeric(16,2)
,ACTUAL_DATE datetime
)
INSERT INTO #Balance
SELECT 332,179304.00,'2009/04/16' UNION ALL
SELECT 332,179252.00,'2009/04/15' UNION ALL
SELECT 332,173697.66,'2009/04/14' UNION ALL
SELECT 332,115454.38,'2009/04/13' UNION ALL
SELECT 332,115454.38,'2009/04/12' UNION ALL
SELECT 5,75406.06,'2009/04/16' UNION ALL
SELECT 5,73406.06,'2009/04/15' UNION ALL
SELECT 5,73406.06,'2009/04/14' UNION ALL
SELECT 5,72406.06,'2009/04/13' UNION ALL
SELECT 5,73406.06,'2009/04/12'
I have following query:
SELECT CUSTOMER_NO
,CURRENT_BALANCE
,min(ACTUAL_DATE) [StartDate]
,max(ACTUAL_DATE) EndDate
,count(1) No_Of_Days
FROM #Balance
GROUP BY CUSTOMER_NO
,CURRENT_BALANCE
ORDER BY CUSTOMER_NO,[StartDate]
The above query is fine if the balance changes and never comes back to the same balance in future.
I get good results for customer number 332, but for customer number 5 the dates and days for the balance 73406.06 are incorrect.
I am not able to think in the right direction. Can anyone point me to the correct direction?
-Vikas Bindra
April 17, 2009 at 8:37 am
WITH CTE AS (
SELECT CUSTOMER_NO,
CURRENT_BALANCE,
ACTUAL_DATE,
ROW_NUMBER() OVER(PARTITION BY CUSTOMER_NO ORDER BY ACTUAL_DATE) -
ROW_NUMBER() OVER(PARTITION BY CUSTOMER_NO,CURRENT_BALANCE ORDER BY ACTUAL_DATE) AS rnDiff
FROM #Balance)
SELECT CUSTOMER_NO,CURRENT_BALANCE,
MIN(ACTUAL_DATE) AS StartDate,
MAX(ACTUAL_DATE) AS EndDate,
COUNT(DISTINCT ACTUAL_DATE) AS No_Of_Days
FROM CTE
GROUP BY CUSTOMER_NO,CURRENT_BALANCE,rnDiff
ORDER BY CUSTOMER_NO,MIN(ACTUAL_DATE)
____________________________________________________
Deja View - The strange feeling that somewhere, sometime you've optimised this query before
How to get the best help on a forum
http://www.sqlservercentral.com/articles/Best+Practices/61537April 20, 2009 at 2:20 am
Thanks Mark!!
-Vikas Bindra
April 22, 2009 at 1:17 pm
Mark (4/17/2009)
WITH CTE AS (
SELECT CUSTOMER_NO,
CURRENT_BALANCE,
ACTUAL_DATE,
ROW_NUMBER() OVER(PARTITION BY CUSTOMER_NO ORDER BY ACTUAL_DATE) -
ROW_NUMBER() OVER(PARTITION BY CUSTOMER_NO,CURRENT_BALANCE ORDER BY ACTUAL_DATE) AS rnDiff
FROM #Balance)
SELECT CUSTOMER_NO,CURRENT_BALANCE,
MIN(ACTUAL_DATE) AS StartDate,
MAX(ACTUAL_DATE) AS EndDate,
COUNT(DISTINCT ACTUAL_DATE) AS No_Of_Days
FROM CTE
GROUP BY CUSTOMER_NO,CURRENT_BALANCE,rnDiff
ORDER BY CUSTOMER_NO,MIN(ACTUAL_DATE)
Very cool, Mark. Better than that, this finally answers the question of why someone would want to do this kind of strange grouping with a real life problem. It's the first time I've seen a real practical use for it. Thanks.
--Jeff Moden
Change is inevitable... Change for the better is not.
Viewing 4 posts - 1 through 3 (of 3 total)
You must be logged in to reply to this topic. Login to reply