Author |
Topic |
Teachme
Starting Member
45 Posts |
Posted - 2008-03-03 : 09:35:26
|
I have a table called Invoice. It has fields such asInvoicenum duedate Amount and status. The status could be open or close meaningwhether the invoice has been paid or not. What i basically want to achieve is tofind which invoice is delinquent by (1-30days,31-60,61-90,91-120 and >120).What happens is if there are open invoices for instance in the month of Decemberand January and the customer made a payment in february for just one month. That paymentgoes towards February invoice leaving December and jan open whearas its supposed to be appliedtowards December invoice but its a bug in the system. However i want to create a report tocalculate true delinquency. Let me clarify by the following exampleInvoicenum duedate amount status100 20071001 500 o101 20071101 500 c102 20071201 500 c103 20080101 500 o104 20080201 500 oNow my query or report shud display the above results as followsInvoiceNum delinquency Amount100 61-90 500 103 31-60 500 104 1-30 500 The open and closed invoices might appear in different variations meaning there could be10 open invoices between 2 closes invoices or anything like that.In other words I just want to be able to list all the open invoices 30 days apart from each otther.I just somehow can't get the right logic for it to work in all cases. If i need todo it thru a stored procedure give any suggestions please. I hope I explained itclearly if not i'll try to elaborate on it more. thanks for your help. |
|
dataguru1971
Master Smack Fu Yak Hacker
1464 Posts |
Posted - 2008-03-03 : 20:24:57
|
[code]Create table #invoice ( company char(1) not null, invoice char(3) not null, duedate datetime not null, amount numeric(10,0) not null, [status] char(1) not null)Insert Into #invoice ( company, invoice, duedate, amount, [status] )SELECT 'A','100', '20071001', 500, 'o' UNION SELECT 'A','101', '20071101', 500, 'c' UNION SELECT 'A','102', '20071201', 500, 'c' UNION SELECT 'A','103', '20080101', 500, 'o' UNION SELECT 'A','104', '20080201', 500, 'o' UNIONSELECT 'B','100', '20071001', 500, 'c' UNION SELECT 'B','101', '20071101', 500, 'o' UNION SELECT 'B','102', '20071201', 500, 'c' UNION SELECT 'B','103', '20080101', 500, 'o' Select a.Company, Invoice, duedate, amount, dpastdue = datediff(d, duedate,maxdate), pastdue = Case When datediff(d, duedate,maxdate) <=30 then '0 to 30' When datediff(d, duedate,maxdate) <=60 then '1 to 30' When datediff(d, duedate,maxdate) <=90 then '1 to 30' When datediff(d, duedate,maxdate) >90 then '91 plus' End FROM #invoice a inner join (Select Company,dateadd(m,1,max(duedate)) as maxdate --adds a month to the highest invoice date From #invoice where [Status] = 'o' Group by Company ) b on a.Company = b.Company Where a.[status] = 'o'results--A 100 2007-10-01 00:00:00.000 500 152 91 plus--A 103 2008-01-01 00:00:00.000 500 60 1 to 30--A 104 2008-02-01 00:00:00.000 500 29 0 to 30--B 101 2007-11-01 00:00:00.000 500 92 91 plus--B 103 2008-01-01 00:00:00.000 500 31 1 to 30 Drop Table #invoice[/code]Fix that bug! telling someone they are 90+, when only 30+ can be bad for business...This code compares the invoice date to 1 month past the highest invoice date for the company. (assumes that March 1 st for a February 1st due date reflects ~30 days, or one statement past due Poor planning on your part does not constitute an emergency on my part. |
 |
|
Teachme
Starting Member
45 Posts |
Posted - 2008-03-04 : 09:09:06
|
I think u might be on the right track as far as what i want but my results would be slightly different. if below was my data in the table as the way its supposed to beSELECT 'A','100', '20071001', 500, 'o' UNION SELECT 'A','101', '20071101', 500, 'c' UNION SELECT 'A','102', '20071201', 500, 'c' UNION SELECT 'A','103', '20080101', 500, 'o' UNION SELECT 'A','104', '20080201', 500, 'o' my results would be as follows:--A 102 500 90 plus days--A 103 500 60 plus days--A 104 500 1-30 daysbecause what i'm trying to do is to apply every closed invoice to the first open invoice and so on. i hope it makes it clear. thanks |
 |
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2008-03-04 : 10:06:01
|
[code]-- prepare test datadeclare @test table (amount int)Insert @testselect 10 union allselect 20 union allselect 30 union allselect 40 union allselect 50 union allselect 60 union allselect 70 union allselect 80-- Peso 1SELECT SUBSTRING(q.[Desc], 3, 8000) AS [Desc], COUNT(*) [Count of Amount], SUM(Amount) [Sum of Amount]FROM ( SELECT CASE WHEN Amount <= 30 THEN '1#Less than or equal to 30' WHEN Amount BETWEEN 31 AND 50 THEN '2#31 to 50' WHEN Amount BETWEEN 51 AND 70 THEN '3#51 to 70' WHEN Amount BETWEEN 71 AND 100 THEN '4#71 to 100' WHEN Amount > 100 THEN '5#Over 100' END AS [Desc], Amount FROM @Test ) qGROUP BY SUBSTRING(q.[Desc], 3, 8000)ORDER BY MIN(LEFT(q.[Desc], 1))-- Peso 2SELECT g.Msg, SUM(CASE WHEN t.Amount IS NULL THEN 0 ELSE 1 END), SUM(CASE WHEN t.Amount IS NULL THEN 0 ELSE t.Amount END)FROM ( SELECT 'Less than or equal to 30' AS Msg, -2147483648 AS minLevel, 30 AS maxLevel UNION ALL SELECT '31 to 50', 31, 50 UNION ALL SELECT 'Fifthyone to 70', 51, 70 UNION ALL SELECT '71 to 100', 71, 100 UNION ALL SELECT 'Over C', 101, 2147483647 ) AS gLEFT JOIN @Test AS t ON t.Amount BETWEEN g.minLevel AND g.maxLevelGROUP BY g.MsgORDER BY MIN(g.minLevel)[/code] E 12°55'05.25"N 56°04'39.16" |
 |
|
dataguru1971
Master Smack Fu Yak Hacker
1464 Posts |
Posted - 2008-03-04 : 14:02:16
|
quote: Originally posted by Teachme I think u might be on the right track as far as what i want but my results would be slightly different. if below was my data in the table as the way its supposed to beSELECT 'A','100', '20071001', 500, 'o' UNION SELECT 'A','101', '20071101', 500, 'c' UNION SELECT 'A','102', '20071201', 500, 'c' UNION SELECT 'A','103', '20080101', 500, 'o' UNION SELECT 'A','104', '20080201', 500, 'o' my results would be as follows:--A 102 500 90 plus days--A 103 500 60 plus days--A 104 500 1-30 daysbecause what i'm trying to do is to apply every closed invoice to the first open invoice and so on. i hope it makes it clear. thanks
That is a little different than your first example ;)Can you apply what Peso demonstrated? Poor planning on your part does not constitute an emergency on my part. |
 |
|
Teachme
Starting Member
45 Posts |
Posted - 2008-03-04 : 14:52:43
|
I have no idea what pesto is trying to suggest...As far as my example is concerned...i know how to calculate difference in days...what i wana do is to list all the open invoices with their due dates changed temporarily...what i mean is if i have one open invoice in the month of january and then a close invoice in the month of february...the system was supposed to post that payment of february towards january but it doesn't do that..so now january invoice is open but the delinquency is not gona be counted since january...it will be counted since february..because we look at that (Feb) payment as if it was posted towards the month of january so the delinquency would be 1-30days (days since 02/01/08 till todays date). i hope now u understand what i'm trying to achieve. thanks |
 |
|
dataguru1971
Master Smack Fu Yak Hacker
1464 Posts |
Posted - 2008-03-04 : 17:09:46
|
[code]Create table #invoice ( company char(1) not null, invoice char(3) not null, duedate datetime not null, amount numeric(10,0) not null, [status] char(1) not null)Insert Into #invoice ( company, invoice, duedate, amount, [status] )SELECT 'A','100', '20071001', 500, 'o' UNION SELECT 'A','101', '20071101', 500, 'c' UNION SELECT 'A','102', '20071201', 500, 'c' UNION SELECT 'A','103', '20080101', 500, 'o' UNION SELECT 'A','104', '20080201', 500, 'o' UNIONSELECT 'B','100', '20071001', 500, 'c' UNION SELECT 'B','101', '20071101', 500, 'o' UNION SELECT 'B','102', '20071201', 500, 'c' UNION SELECT 'B','103', '20080101', 500, 'o' Select main.Company, main.Invoice, main.duedate, main.amount, Case When datediff(d, main.duedate,getdate()) <=30 then '0 to 30' When datediff(d, main.duedate,getdate()) <=60 then '30 to 59' When datediff(d, main.duedate,getdate()) <=90 then '61 to 90' When datediff(d, main.duedate,getdate()) >90 then '91 plus' End as PastDueFROM (Select Company,Invoice, DueDate,Amount,[Status], (select Count(*)+1 from #invoice b where b.Invoice < a.invoice and b.Company = a.Company) as Ct FROM #invoice a Group by Company,Invoice, DueDate,Amount,[Status]) main left join (Select Company,Invoice, DueDate,Amount,[Status], (select Count(*) from #invoice b where b.Invoice < a.invoice AND a.[Status] = 'c' and b.Company = a.Company) as Ct FROM #invoice a Where a.[Status] = 'c' Group by Company,Invoice, DueDate,Amount,[Status]) paid on main.Company = paid.Company and main.ct =paid.ctWhere paid.DueDate is null--results--A 102 2007-12-01 00:00:00.000 500 91 plus--A 103 2008-01-01 00:00:00.000 500 61 to 90--A 104 2008-02-01 00:00:00.000 500 30 to 59--B 100 2007-10-01 00:00:00.000 500 91 plus--B 102 2007-12-01 00:00:00.000 500 91 plus--B 103 2008-01-01 00:00:00.000 500 61 to 90 Drop Table #invoice[/code]That seems to do the trick. Poor planning on your part does not constitute an emergency on my part. |
 |
|
|
|
|