我正在使用两张桌子。我们称之为“客户”和“积分”。
点数表如下所示:
Account Year M01 M02 M03 M04 M05 M06 M07 M08 M09 M10 M11 M12
123 2011 10 0 0 0 10 0 10 0 0 0 0 10
123 2012 0 0 0 0 10 0 0 10 10 10 10 20
123 2013 5 0 0 0 0 0 0 0 0 0 0 0
但这些观点在滚动的12个月内有效。计算当前客户的积分很简单,但挑战是针对不再活跃的客户。假设客户123在2013年1月失效,我们只想计算2013年1月12日至1月1日。这是另一个表,Customers,其中的内容,让我们简化并说它看起来像这样:
Account End Date
123 20130105
现在,我想要做的是创建一个计算每个客户拥有的点数的查询。 (活跃客户目前为12个月,过去12个月他们对不再活跃的客户有效。)
以下是更多信息:
这是一个非常复杂的问题。如果有什么我可以解释得更好,请告诉我。谢谢!
答案 0 :(得分:4)
不幸的是,对于points
的表结构,您必须取消数据。 unpivot 将多列中的数据转换为行。一旦数据在行中,就可以更容易地加入,过滤数据并为每个帐户计算总积分。取消数据的代码将类似于:
select account,
cast(cast(year as varchar(4))+'-'+replace(month_col, 'M', '')+'-01' as date) full_date,
pts
from points
unpivot
(
pts
for month_col in ([M01], [M02], [M03], [M04], [M05], [M06], [M07], [M08], [M09], [M10], [M11], [M12])
) unpiv
见SQL Fiddle with Demo。该查询给出了与此类似的结果:
| ACCOUNT | FULL_DATE | PTS |
------------------------------
| 123 | 2011-01-01 | 10 |
| 123 | 2011-02-01 | 0 |
| 123 | 2011-03-01 | 0 |
| 123 | 2011-04-01 | 0 |
| 123 | 2011-05-01 | 10 |
数据采用此格式后,您可以加入Customers
表格以获取每个account
的总分数,因此代码类似于以下内容:
select
c.account, sum(pts) TotalPoints
from customers c
inner join
(
select account,
cast(cast(year as varchar(4))+'-'+replace(month_col, 'M', '')+'-01' as date) full_date,
pts
from points
unpivot
(
pts
for month_col in ([M01], [M02], [M03], [M04], [M05], [M06], [M07], [M08], [M09], [M10], [M11], [M12])
) unpiv
) p
on c.account = p.account
where
(
c.enddate = '9999-12-31'
and full_date >= dateadd(year, -1, getdate())
and full_date <= getdate()
)
or
(
c.enddate <> '9999-12-31'
and dateadd(year, -1, [enddate]) <= full_date
and full_date <= [enddate]
)
group by c.account
答案 1 :(得分:2)
糟糕的数据结构。首先要做的是取消它。然后你得到一个以年 - 月 - 点为列的表。
从这里,您可以选择最近的12个月。事实上,您甚至不必担心客户何时离开,因为从那时起他们可能没有收集积分。
这是SQL中的一个例子:
with points as (
select 123 as account, 2012 as year,
10 as m01, 0 as m02, 0 as m03, 0 as m04, 10 as m05, 0 as m06,
10 as m07, 0 as m08, 0 as m09, 0 as m10, 0 as m11, 10 as m12
),
points_ym as (
select account, YEAR, mon, cast(right(mon, 2) as int) as monnum, points
from points
unpivot (points for mon in (m01, m02, m03, m04, m05, m06, m07, m08, m09, m10, m11, m12)
) as unpvt
)
select account, SUM(points)
from points_ym
where year*12+monnum >= year(getdate())*12+MONTH(getdate()) - 12
group by account