加入两个表来计算不同的日期

时间:2014-11-12 18:31:56

标签: sql sql-server join count

我有一个带有列的表A:

id, transactiondate, pointsordered

表B

id,redemptiondate,pointsused

表C

as

id,joindate

我想要什么

日期范围需要所有数据,例如2014-01-01至2014-02-01 YYYY-MM-DD

  • 按日期计算的总ID数(表a中的ID数)
  • 此日期第一笔交易的帐户数

  • 按日期排序的总积分(表a中的积分总和)

  • 在该日期兑换的帐户数(表b中的ID数)
  • 该日期的点数(表b中的点数之和)

  • 按日期加入的新客户

我理解id是表b和表c的外键,但我如何确保匹配日期?

例如,如果我按日期加入,例如a.transactiondate = b.redemption.date,它会向我提供在该日期进行交易并在该日期兑换的所有客户。

我想要计算在该日期进行交易的所有客户以及在该日期已兑换的客户的数量(不管他们何时进行交易的事实)

以下是我尝试的内容

select count( distinct a.id) as noofcustomers, sum(a.pointsordered), sum(b.pointsused), count(distinct b.id)
from transaction as a join redemption as b on a.transactiondate=b.redemptiondate
where a .transactiondate between '2014-01-01' and '2014-02-01' 
group by a.transactiondate,b.redemptiondate

1 个答案:

答案 0 :(得分:0)

我首先按表对数据进行分组,然后按日期加入结果。您不应该使用内部联接,因为如果一方没有匹配的记录,例如在给定日期没有交易而是兑换,则可能会丢失数据。如果您拥有该范围内的日期列表,这将有所帮助。如果你没有,你可以使用CTE建立一个。

declare @from date = '2014-01-01'
declare @to date = '2014-02-01'
;
with dates as
(
  select @from as [date]
  union all
  select dateadd(day, [date], 1) as d from dates where [date] < @to
)
, orders as
(
  select transactiondate as [date], count(distinct id) as noofcustomers, sum(pointsordered) as pointsordered
  from [transaction]
  where transactiondate between @from and @to
  group by transactiondate 
)
, redemptions as
(
  select redemptiondate as [date], count(distinct id) as noofcustomers, sum(pointsused) as pointsused
  from [redemption]
  where redemptiondate between @from and @to
  group by redemptiondate 
)
, joins as
(
  select joindate as [date], count(distinct id)  as noofcustomers
  from [join]
  where joindate between @from and @to
  group by joindate
)
, firsts as
(
  select transactiondate as [date], count(distinct id) as noofcustomers
  from [transaction] t1
  where transactiondate between @from and @to
  and not exists (
    select * from [transaction] t2 where t2.id = t1.id and t2.transactiondate < t1.transactiondate)
  group by transactiondate 
)
select 
  d.[date], 
  isnull(o.noofcustomers,0) as noofcustomersordered,
  isnull(o.pointsordered,0) as totalpointsordered,
  isnull(f.noofcustomers,0) as noofcustomersfirsttran,
  isnull(r.noofcustomers,0) as noofcustomersredeemed,
  isnull(r.pointsused,0) as totalpointsredeemed,
  isnull(j.noofcustomers,0) as noofcustomersjoined  
from dates d
left join orders o on o.[date] = d.[date]
left join redemptions r on r.[date] = d.[date]
left join joins j on j.[date] = d.[date]
left join firsts f on f.[date] = d.[date]

请注意,我没有运行查询,因此可能会出错,但我认为一般的想法很明确。