Рекурсивный cte со значениями из 2 таблиц - PullRequest
0 голосов
/ 02 мая 2018

Мне нужна помощь с этим, пожалуйста.

Я хотел бы создать рекурсивный запрос со значениями из таблицы для якоря, умноженными на коэффициент из другой таблицы.

Позвольте мне быть более точным:

Состав и заполнение таблиц:

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) * Коэфф (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

1 Ответ

0 голосов
/ 02 мая 2018

Это дает желаемый результат:

;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

Проблема с вашим решением в том, что якорь не начинается с правильной цены, вы должны умножить цену на коэффициент на якоре. Имейте в виду, что якорь является первым набором результирующего 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

*/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...