2009-10-15 110 views
0

我有一张表,其中包含每月的账单记录数据。所以说1月/ 2月收费Customer 1234,1月/ 2月/ 3月收帐Customer 2345。如何将这些分组显示给我一个并行的每月结算周期。但是,还需要有非并发红嘴个月,所以Customer 3456被标榜需要二月/ APL /月/ 8SQL如何使多个查询中的一个查询

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

结果:

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 

有什么建议?

+1

从你的描述,而不是并发,你可能意味着连续?即不是“同时”,而是“在接下来的几个月”? – 2009-10-15 20:32:05

+0

你的RDBMS是什么? – cmsjr 2009-10-15 20:35:50

+0

另外,月份如何储存,数字或名称? – cmsjr 2009-10-15 20:38:28

回答

1

如果月份被存储为一个日期时间字段,你可以使用DATEDIFF计算第一个和最后法案之间的月数。如果经过的月数等于账单总数,则账单连续。

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 

如果您将结算月份存储为整数,那么您可以减去而不是使用DATEDIFF。将WHEN行替换为:

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

但是在那种情况下,我想知道您是如何区分年份的。

+0

感谢这帮了很多 – 2009-10-16 12:14:25

+0

每月只有一个账单?我完全错过了。 – 2009-10-16 13:30:00

+0

假设根据样本数据,如果假设不正确,您可以将“from @billing”替换为“from(从客户名称中选择custname,billdate from billname,billdate)sub” – Andomar 2009-10-16 13:48:12

0

怎么样:

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

这是有点我需要,但我还需要多个WHERE条件,我认为CASE声明将做,谢谢 – 2009-10-16 12:21:32

1

如果几个月都在一个序列,我们都限制我们的搜索到某一年,然后(结算时间)最小(月)+计数 - 1应该= MAX(月)。

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 
+0

感谢这有助于 – 2009-10-16 12:20:31

1

这里的建议基于一个假设,即在同一个月内您永远不会向客户收取两次或更多费用。如果这不是一个安全的假设,你需要一个不同的方法。让我们知道如果是这样的话。

+1

好点,可以用群组解决通过子查询 – Andomar 2009-10-16 09:48:03

+0

您是对的,但我不需要知道他们是否在一个月内被收取超过一次的费用。我认为GROUP BY会照顾到这种情况。查询是否在给定的时间内进行一些业务分析分析。 – 2009-10-16 12:18:00

0

你忽略了一些重要的信息(比如如何月份的存放处)你用什么数据库,但这里的,你可以开始一个合乎逻辑的做法:

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 

假设月份这里是一个连续的整数字段从系统中第一个可能的月份开始递增1,这会为您提供每个客户对每个月累计的结算额度,以及一个额外的标志,其中包含对客户同时进行结算的月份的“连续”那些在客户没有收到账单的月份之后的月份中,“不连续”。

然后:

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

会给你或多或少你想要什么(其中LISTOF是某种类型的COALESCE函数依赖你使用的确切数据库)。

+1

这种方法将始终将第一个月列为非连续。 – Andomar 2009-10-16 09:47:02

+0

是的,那是事实。在我未说明的假设中,无论是视图定义还是第二个最终SELECT都会将查询限制为小于数据库中整个月份的范围。 – 2009-10-16 11:18:53

+0

是的,我之前试过UNION ALL和SUB SELECTS,而且我得到了我需要的结果,但我认为CASE声明是最好的方法,最终我会喜欢。感谢您的输入 – 2009-10-16 12:19:42