假设我有以下数据:
ContactDate Zip
10-1-2016 90210
10-7-2016 90211
10-8-2016 90210
10-8-2016 90211
我想总结一下30天内每个拉链发生的联系人数量。然而,它不是按月,而是用户的月份结算日。那么就说那天是每个月的第二天......
我正在尝试获得以下结果:
BillingMonthStart Zip Count
9-2-2016 90210 1
10-2-2016 90210 1
10-2-2016 90211 2
这是我的尝试(显然表结构不同,我将开始修复上面的例子):
select
C1.ContactDate, count(C1.ContactDate)
from
dbo.contacts c1 join dbo.contacts C2 on
C2.contactdate between C1.ContactDate AND dateadd(day, 30, C1.ContactDate)
AND c1.account = c2.accountid
join payment.dbo.AccountBilling B on c1.accountid = B.AccountID
where
c1.account = @accountid
and C1.ContactDate >= @start_date
and C1.ContactDate <= @end_date
and DAY(C1.ContactDate) = B.BillingDOM
Group by C1.contactDate
这里的问题是,如果该帐户确实在结算日获得了联系,那么我将无法获得该月的结果。
修改 首先,对于形成不良的问题感到抱歉。我已经弄明白了(虽然我确信有更好的方法)。这是我做的:
between
来自#2和billingDate + 1个月的billingDate加入联系人数据表这是SQL:
DECLARE @start_date DateTime
DECLARE @end_date DateTime
DECLARE @accountid int
DECLARE @billing_dom tinyint
SET @start_date = '2016-01-01'
SET @end_date = '2016-12-31'
SET @accountid = 6045032;
select @billing_dom = BillingDOM
from Payment.dbo.AccountBilling
where AccountID = @accountid;
WITH cte_months AS
(
SELECT
BillingDate = CAST(CAST(datepart(yyyy, @start_date) AS varchar) + '-' + CAST(datepart(mm, @start_date) AS varchar) + '-' + CAST(@billing_dom AS varchar) AS DATETIME),
dt = @start_date
UNION ALL
SELECT
BillingDate = DateAdd(mm, 1, BillingDate),
dt = DATEADD(mm, 1, dt)
FROM
cte_months
WHERE
dt < DATEADD(mm, -1, @end_date)
)
--SELECT * FROM cte_months
select
cte_months.BillingDate, count(C.ContactDate) as Contacts
from
cte_months left join dbo.contacts C on
C.ContactDate between cte_months.BillingDate and dateadd(mm, 1, cte_months.BillingDate)
where
C.accountid = @accountid
Group by cte_months.BillingDate
答案 0 :(得分:0)
以下是如何实现此目的的示例,使用案例陈述按结算周期对数据进行分组。如果不确切知道你的表格是什么样子,很难确切地知道select语句应该是什么,但一般概念仍然适用于此:
DECLARE @myTable TABLE (ContactDate DATE, Zip INT);
INSERT @myTable VALUES ('10-1-2016', 90210), ('10-7-2016', 90211), ('10-8-2016', 90210), ('10-8-2016', 90211);
DECLARE @myBilling TABLE (Zip INT, BillingDay INT);
INSERT @myBilling VALUES (90210, 2), (90211, 2);
SELECT CAST(CASE WHEN DATEPART(DAY, T.ContactDate) < B.BillingDay
THEN DATEADD(DAY, B.BillingDay - 1, DATEADD(MONTH, DATEDIFF(MONTH, 0, T.ContactDate) - 1, 0))
ELSE DATEADD(DAY, B.BillingDay - 1, DATEADD(MONTH, DATEDIFF(MONTH, 0, T.ContactDate), 0))
END AS DATE) BillingPeriod
, T.Zip
, COUNT(*) theCount
FROM @myTable T
JOIN @myBilling B ON B.Zip = T.Zip
GROUP BY T.Zip
,CASE WHEN DATEPART(DAY, T.ContactDate) < B.BillingDay
THEN DATEADD(DAY, B.BillingDay - 1, DATEADD(MONTH, DATEDIFF(MONTH, 0, T.ContactDate) - 1, 0))
ELSE DATEADD(DAY, B.BillingDay - 1, DATEADD(MONTH, DATEDIFF(MONTH, 0, T.ContactDate), 0))
END;
答案 1 :(得分:0)
您是按月分组(28至31天),还是总是30天?
如果它总是30天,那么除了任何其他非日期列之外,还要分组。
ceiling(cast(datediff(day,BillingMonthStart,ContactDate) AS FLOAT)/30)
这将为您提供BillingMonthStart和ContactDate四舍五入之间的30天间隔。也就是说,它在0天的同一天计算联系,包括第30天。如果您希望第30天成为新组,那么:
ceiling((cast(datediff(day,BillingMonthStart,ContactDate) AS FLOAT)+1)/30)
如果您希望按月持续时间而不是静态30天,那么:
datediff(month,@BillingMonthStart,@ContactDate) - CASE
WHEN datepart(day,@BillingMonthStart) > datepart(day,@ContactDate) THEN 1
ELSE 0
END