我希望有人可以指出我正确的方向来编写一个返回计算值的查询,该计算值使用查找来查找以前的值。例如,我有两个表,如下所示。我在一个视图中将它们连接在一起,但我需要添加一个额外的列,它给我一个以前的值:
CEO_Table:
CEO_Name | FromDate | ToDate
-----------------------------------------
Glen Bryant | 2000-11-30 | 2002-06-30
Bob Costa | 2002-6-30 | 2004-9-15
Gill Bogart | 2004-9-15 | 2009-10-01
Ben Olson | 2009-10-01 | 2010-08-10
Expense_Table:
Date | AsOf_Expenses_Total_Millions (as Exp)
-----------------------------------------
2001-01-01 | 100
2002-01-01 | 300
2003-01-01 | 155
2004-01-01 | 350
2005-01-01 | 400
2006-01-01 | 600
2007-01-01 | 150
2008-01-01 | 200
2009-01-01 | 300
2010-01-01 | 500
我正在尝试使用这两个表构建一个视图,该视图添加了3个额外的列: CEO(在给定日期查找CEO); LastCEOExp(查看以前CEO的最后费用值); PercentChange(使用LastCEOExp计算百分比变化,使用公式(Exp - LastCEOExp)/(LastCEOExp)* 100)
CEO_Expenses_Change_Over_Time:
Date | Exp | CEO_Name | LastCEOExp | PercentChange
-------------------------------------------------------------------
2001-01-01 | 100 | Glenn Bryant | NULL | NULL
2002-01-01 | 300 | Glenn Bryant | NULL | NULL
2003-01-01 | 155 | Bob Costa | 300 | -48%
2004-01-01 | 350 | Bob Costa | 300 | 16%
2005-01-01 | 400 | Gill Bogart | 350 | 14%
2006-01-01 | 600 | Gill Bogart | 350 | 71%
2007-01-01 | 150 | Gill Bogart | 350 | -57%
2008-01-01 | 200 | Gill Bogart | 350 | -42%
2009-01-01 | 300 | Gill Bogart | 350 | -14%
2010-01-01 | 500 | Ben Olson | 300 | 66%
我已经加入了CEO_Name列,但是我遇到了LastCEOExp列的问题。一旦我将该列固定下来,我可以将PercentChange列放在一起。有人有什么建议吗?我猜我可以使用CTE来完成这项任务,但我不确定从哪里开始。以下是我的内容:
SELECT exp.[Date]
,exp.[Exp]
,ceo.[CEO_Name]
FROM [Expense_Table] exp
INNER JOIN [CEO_Table] ceo
ON exp.[Date] between ceo.[FromDate] and ceo.[ToDate]
答案 0 :(得分:0)
我做了这样的代码,我使用
ROW_NUMBER(Transact-SQL) http://msdn.microsoft.com/en-us/library/ms186734.aspx
在你的情况下,ROW_NUMBER可以随着时间的推移然后你玩ROW_ID 你可以创建函数返回表SHIFT + 1 ROW_ID然后JOIN表,小心你需要在使用临时表,视图时为ROW_ID上的大集添加索引...
你创建函数的第二个选项(参数datetime)返回值将适用于小集合
SELECT A.*,PrevYear.*, cast(( ROUND((cast(A.[Exp] as float) - cast(PrevYear.[Exp] as float) ) / cast(A.[Exp] as float) * 100 ,2) ) as varchar) + '%' as PercentChange from
(SELECT ROW_NUMBER() OVER(ORDER BY exp.[Date] DESC) AS Row, exp.[Date]
,exp.[AsOf_Expenses_Total_Millions] as [Exp]
,ceo.[CEO_Name]
FROM [Expense_Table] exp
INNER JOIN [CEO_Table] ceo
ON exp.[Date] between ceo.[FromDate] and ceo.[ToDate]
) A left join
(SELECT (ROW_NUMBER() OVER(ORDER BY exp.[Date] DESC) -1) AS Row, exp.[Date]
,exp.[AsOf_Expenses_Total_Millions] as [Exp]
,ceo.[CEO_Name] as PrevCEO_Name
FROM [Expense_Table] exp
INNER JOIN [CEO_Table] ceo
ON exp.[Date] between ceo.[FromDate] and ceo.[ToDate]
) PrevYear
on A.row = PrevYear.row
order by A.row
答案 1 :(得分:0)
您需要熟悉SQL Server中的window functions。这是一个解决方案:
WITH
tmp AS
(
SELECT exp.Date,
CEO_Name,
exp.Exp,
DENSE_RANK() OVER (ORDER BY ceo.FromDate) AS CEOOrder,
ROW_NUMBER() OVER (PARTITION BY ceo.CEO_Name ORDER BY exp.Date DESC)
AS ExpOrder
FROM CEO_Table ceo
INNER JOIN Expense_Table exp ON exp.Date BETWEEN ceo.FromDate AND ceo.ToDate
)
SELECT t1.Date,
t1.CEO_Name,
t1.Exp,
t2.Exp AS LastCEOExp,
(t1.Exp - t2.Exp) / t2.Exp * 100 AS PercentChange
FROM tmp t1
LEFT JOIN tmp t2 ON t1.CEOOrder = t2.CEOOrder + 1 -- This select the last CEO
AND t2.ExpOrder = 1 -- This select his last pay
ORDER BY t1.CEOOrder, t1.ExpOrder DESC
答案 2 :(得分:-1)
我认为领先/滞后可能会让你得到你想要的东西:
如果OBJECT_ID(N'tempdb .. ## lag_table 'N'U')不为空