开发者

SQL how to make one query out of multiple ones

I have a table th开发者_运维技巧at holds monthly data of billing records. so say Customer 1234 was billed in Jan/Feb and Customer 2345 was billing Jan/Feb/Mar. How can I group these to show me a concurrent monthly billing cycle. But also need to have non-concurrent billed months, so Customer 3456 was billed Feb/Apl/Jun/Aug

SELECT custName, month, billed, count(*) as Tally
FROM db_name
WHERE
GROUP BY

Results needed:

Customer 1234 was billed for 2 months Concurrent
Customer 2345 was billed for 3 months Concurrent
Customer 3456 was billed for 4 months Non-Concurrent

Any suggestions?


If the month is stored as a datetime field, you can use DATEDIFF to calculate the number of months between the first and the last bill. If the number of elapsed months equals the total number of bills, the bills are consecutive.

select 
 'Customer ' + custname + ' was billed for ' +
 cast(count(*) as varchar) + ' months ' + 
 case 
  when datediff(month,min(billdate),max(billdate))+1 = count(*) 
   then 'Concurrent'
  else 'Non-Concurrent'
 end
from @billing
where billed = 1
group by custname

If you store the billing month as an integer, you can just subtract instead of using DATEDIFF. Replace the WHEN row with:

when max(billdate)-min(billdate)+1 = count(*) 

But in that case I wonder how you distinguish between years.


If the months were all in a sequence, and we are limiting our search to a particular year then Min(month) + Count(times billed) - 1 should = Max(month).

declare @billing table(Custname varchar(10), month int, billed bit)

insert into @billing values (1234, 1, 1)
insert into @billing values (1234, 2, 1)
insert into @billing values (2345, 3, 1)
insert into @billing values (2345, 4, 1)
insert into @billing values (2345, 5, 1)
insert into @billing values (3456, 1, 1)
insert into @billing values (3456, 3, 1)
insert into @billing values (3456, 9, 1)
insert into @billing values (3456, 10, 1)

Select CustName, Count(1) as MonthsBilled, 
Case 
  when Min(Month) + Count(1) - 1 = Max(Month) 
  then 1 
  else 0 
end Concurrent
From @billing 
where Billed = 1
Group by CustName

Cust   Months   Concurrent 
1234    2          1
2345    3          1
3456    4          0


The suggestions here work based on an assumption that you will never bill a customer twice or more in the same month. If that isn't a safe assumption, you need a different approach. Let us know if that's the case.


how about:

SELECT custName, month, count(*) as tally
from billing
where billed = 1
group by custName, month


You left out some important information (like how Month is stored) and what database you're using, but here's a logical approach that you can start with:

CREATE VIEW CustomerBilledInMonth (CustName, Month, AmountBilled, ContinuousFlag) AS
    SELECT CustName, Month, SUM(AmountBilled), 'Noncontinuous'
    FROM BillingTable BT1 
    WHERE NOT EXISTS 
    (SELECT * FROM BillingTable BT2 WHERE BT2.CustName = BT1.CustName AND BT2.Month = BT1.Month - 1) 
    GROUP BY CustName, Month
    UNION
    SELECT CustName, Month, SUM(AmountBilled), 'Continuous'
    FROM BillingTable BT1 
    WHERE EXISTS 
    (SELECT * FROM BillingTable BT2 WHERE BT2.CustName = BT1.CustName AND BT2.Month = BT1.Month - 1) 
    GROUP BY CustName, Month

Assuming that Month here is a consecutive integer field incremented by one from the first possible month in the system, this gives you with each customer's billing for each month summed up, and an additional flag containing 'Continuous' for those months that followed a month in which the customer was also billed and 'Noncontinuous' for those months that followed a month in which the customer was not billed.

Then:

SELECT CustName, LISTOF(Month), SUM(AmountBilled), MAX(ContinuousFlag) 
    FROM CustomerBilledInMonth GROUP BY CustName

will give you more or less what you want (where LISTOF is some kind of COALESCE type function dependent on the exact database you're using).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜