我需要一些帮助。
我想创建一个递归查询,其中包含来自锚表的值,再乘以另一个表中的系数。
让我更明确一点:
表格结构和填充:
create table T
(
Site varchar(10) primary key,
Price money,
Year int
);
create table B
( Site varchar(10),
Coeff float,
Year int
);
insert into T values /* Each Site appears only once here */
('A', 125.10, 2003),
('B', 78.10, 2002),
('C', 23.34, 2001)
insert into B values /* Each (Site,Year) appears only once here */
('A', 12, 2003),
('A', 0.111, 2004),
('B', 0.322, 2002),
('B', 0.333, 2003),
('C', 0.555, 2001),
('C', 0.666, 2002)
我的递归公式为: 价格(n)=价格(n-1)* Coeff(n-1) (其中n是年份)
这是我的最后一次尝试:
;WITH cte
AS (SELECT T.Site, T.Year, T.Price as RootPrice FROM T
UNION ALL
SELECT T.Site, T.Year, CAST(cte.RootPrice * B.Coeff AS MONEY) AS PriceYear
FROM T INNER JOIN cte ON T.Site = cte.Site AND T.Year = cte.Year INNER JOIN B ON cte.Year = B.Year AND cte.Site = B.Site)
SELECT * FROM cte
这个cte无休止地运行。我错过了什么?
修改:
需要输出:
Site | Price | Year
---------------------------
A | 1501.2 | 2003
A | 166.78 | 2004
B | 25.15 | 2002
B | 8.37 | 2003
C | 12.95 | 2001
C | 8.63 | 2002
答案 0 :(得分:2)
这会产生您想要的输出:
;WITH CTE AS
(
SELECT
Site = T.Site,
Year = T.Year,
Price = CONVERT(MONEY, T.Price * B.Coeff)
FROM
T AS T
INNER JOIN B AS B ON
T.Site = B.Site AND
T.Year = B.Year
UNION ALL
SELECT
Site = C.Site,
Year = C.Year + 1,
Price = CONVERT(MONEY, C.Price * B.Coeff)
FROM
CTE AS C
INNER JOIN B AS B ON
C.Site = B.Site AND
C.Year + 1 = B.Year
)
SELECT
*
FROM
CTE AS C
ORDER BY
C.Site,
C.Year
您的解决方案的问题是锚点不是以正确的价格开头,您应该将价格与锚点上的coeff相乘。请记住,锚是第一组生成的CTE,它包含在其中。
所以你的主播:
SELECT
T.Site,
T.Year,
T.Price as RootPrice
FROM
T
应该从当年的正确价格开始:
SELECT
Site = T.Site,
Year = T.Year,
Price = CONVERT(MONEY, T.Price * B.Coeff)
FROM
T AS T
INNER JOIN B AS B ON
T.Site = B.Site AND
T.Year = B.Year
并删除递归集上的T
引用,因为您不再需要它了。
如果您还想查看根价格,可以使用递归连接表达式篡改一下:
;WITH CTE AS
(
SELECT
Site = T.Site,
Year = T.Year,
Price = T.Price,
IsRoot = 1
FROM
#T AS T
UNION ALL
SELECT
Site = C.Site,
Year = CASE WHEN C.IsRoot = 1 THEN C.Year ELSE C.Year + 1 END,
Price = CONVERT(MONEY, C.Price * B.Coeff),
IsRoot = 0
FROM
CTE AS C
INNER JOIN #B AS B ON C.Site = B.Site
WHERE
(C.IsRoot = 1 AND C.Year = B.Year) OR
(C.IsRoot = 0 AND C.Year + 1 = B.Year)
)
SELECT
*
FROM
CTE AS C
ORDER BY
C.Site,
C.Year,
C.IsRoot DESC
/*
Results:
Site Year Price IsRoot
---------- ----------- --------------------- -----------
A 2003 125,10 1
A 2003 1501,20 0
A 2004 166,6332 0
B 2002 78,10 1
B 2002 25,1482 0
B 2003 8,3744 0
C 2001 23,34 1
C 2001 12,9537 0
C 2002 8,6272 0
*/