3

样品表

CustomerId | VoucherId | CategoryId | StartDate | EndDate
-------------------------------------------------------------
        10 |         1 |          1 | 2013-09-01| 2013-09-30
        10 |         1 |          2 | 2013-09-01| 2013-09-30
        11 |         2 |          1 | 2013-09-01| 2013-11-30
        11 |         2 |          2 | 2013-09-01| 2013-11-30
        11 |         2 |          3 | 2013-09-01| 2013-11-30
        10 |         3 |          1 | 2013-10-01| 2013-12-31
        10 |         3 |          2 | 2013-10-01| 2013-12-31
        11 |         4 |          1 | 2013-12-01| 2014-04-30

在上面的示例记录中,我想找出客户凭证覆盖的总月数

我需要表格中的输出

CustomerId | Months
--------------------
        10 | 4
        11 | 8

问题是凭证可以有多行用于不同的 CategoryId...

我将凭证涵盖的月份计算为 DATEDIFF(MM, StartDate, EndDate) + 1...

当我应用 SUM(DATEDIFF(MM, StartDate, EndDate)) GROUP BY VoucherId, StartDate, EndDate 时,我给出了错误的结果,因为 VoucherId 有多行......

我得到这样的东西......

CustomerId | Months
--------------------
        10 | 8
        11 | 14

CategoryId 在这种情况下没用

谢谢

4

4 回答 4

4

实际上,在您的情况下(当每个类别的句点相等时)您可以使用此查询:

with cte as (
    select distinct
        CustomerId, StartDate, EndDate
    from Table1
)
select CustomerId, sum(datediff(mm, StartDate, EndDate) + 1) as diff
from cte
group by CustomerId

sql fiddle demo

于 2013-10-11T17:00:54.563 回答
0

您正在按查询中不需要的列进行分组。

SQLFiddle!

于 2013-10-11T17:00:45.473 回答
0

尝试这个:

SELECT
   T.CustomerId,
   T.VoucherId,
   SUM(DATEDIFF(MM, T1.FirstStartDate, T1.LastEndDate)) AS Months
FROM #YourTable T
JOIN
(
    SELECT
        CustomerId,
        VoucherId,
        MIN(StartDate) AS FirstStartDate,
        MAX(EndDate) AS LastEndDate
    FROM #YourTable T1
    GROUP BY CustomerId, VoucherId
) ON T.CustomerId = T1.CustomerId AND T.VoucherId = T1.VoucherId

这是假设您在第一个开始日期和最后一个结束日期之间没有间隔。如果这样做,您可能需要编辑内部选择。但想法是让内部选择确定您的日期范围(并忽略类别),然后让外部选择总结您的月份。

于 2013-10-11T17:05:35.710 回答
0

sql fiddle demo

这个 SQL Fiddle 解决了您的顾虑。您需要生成一个日历表,以便您可以将日期加入其中。然后,您可以为每个客户计算不同的 MonthYears。

create table test(
  CustomerId int,
  StartDate date,
  EndDate date
  )

insert into test
values 
  (10, '9/1/2013', '9/30/2013'),
  (10, '9/1/2013', '9/30/2013'),
  (11, '9/1/2013', '11/30/2013'),
  (11, '9/1/2013', '11/30/2013'),
  (11, '9/1/2013', '11/30/2013'),
  (10, '10/1/2013', '12/31/2013'),
  (10, '10/1/2013', '12/31/2013'),
  (11, '12/1/2013', '4/30/2014')

create table calendar(
  MY varchar(10),
  StartDate date,
  EndDate date
  )

insert into calendar
values 
  ('9/2013', '9/1/2013', '9/30/2013'),
  ('10/2013', '10/1/2013', '10/31/2013'),
  ('11/2013', '11/1/2013', '11/30/2013'),
  ('12/2013', '12/1/2013', '12/31/2013'),
  ('1/2014', '1/1/2014', '1/31/2014'),
  ('2/2014', '2/1/2014', '2/28/2014'),
  ('3/2014', '3/1/2014', '3/31/2014'),
  ('4/2014', '4/1/2014', '4/30/2014')

select
  t.CustomerId, 
  count(distinct c.MY)
from
  test t
  inner join calendar c
    on t.StartDate <= c.EndDate
      and t.EndDate >= c.StartDate
group by
  t.CustomerId
于 2013-10-11T17:08:22.200 回答