tsql выберите с рекурсией - PullRequest
       1

tsql выберите с рекурсией

0 голосов
/ 23 февраля 2012

У меня есть таблица со следующей структурой

Id|State|Quan|SellQuan|LastId
3 |2    | 5  | 0      |2
2 |3    |10  | 5      |1
1 |3    |15  | 5      |NULL

LastId указан в поле Id, мне нужно вычислить значение на следующем шаге: возьмите Quan из Id = 3, затем добавьте все sellquan с идентификатором Id, указанным в предыдущем LastId. это значит Id = 3 - lastId = 2 => принять значение из поля Id = 2 sellquan, а затем проверить, если lastId не равно NULL В моем примере LastId = 1 => Take Id = 1 значение SellQaun Результат: 5 + 5+ 5 = 15

Ответы [ 2 ]

1 голос
/ 24 февраля 2012

Я не совсем уверен, что вы хотите. Но я попробую.

Первые тестовые данные:

DECLARE @tbl TABLE(Id INT,State INT,Quan INT,SellQuan INT,LastId INT)
INSERT INTO @tbl
VALUES
    (3,2,5,0,2),
    (2,3,10,5,1),
    (1,3,15,5,NULL)

Тогда рекурсивная функция выглядит так:

DECLARE @Id INT=1
;WITH CTE(Id,parentId,SellQuan,topParent)
AS
(
    SELECT
        tbl.Id,
        tbl.LastId AS parentId,
        (CASE 
            WHEN EXISTS(SELECT NULL FROM @tbl AS tbl2 WHERE tbl2.LastId=tbl.Id)
            THEN tbl.SellQuan
            ELSE tbl.Quan
        END) AS SellQuan,
        tbl.Id AS topParent
    FROM
        @tbl AS tbl
    WHERE
        tbl.Id=@Id
    UNION ALL
    SELECT
        tbl.Id,
        tbl.LastId AS parentId,
        (CASE 
            WHEN EXISTS(SELECT NULL FROM @tbl AS tbl2 WHERE tbl2.LastId=tbl.Id)
            THEN tbl.SellQuan
            ELSE tbl.Quan
        END) AS SellQuan,
        CTE.topParent AS topParent
    FROM
        @tbl AS tbl
        JOIN CTE
            ON CTE.Id=tbl.LastId
)
SELECT
    CTE.topParent AS id,
    SUM(CTE.SellQuan) AS SellQaunResult
FROM
    CTE
GROUP BY
    CTE.topParent

Надеюсь, это поможет

0 голосов
/ 27 февраля 2012

Исходя из того, что вы просите, я думаю, что у вас есть опечатка в таблице примеров.Если вы внесете следующие изменения, это изменит сложность CTE:

Id|State|Quan|SellQuan|LastId
3 |2    | 5  | 5      |2
2 |3    |10  | 5      |1
1 |3    |15  | 5      |NULL

Мое внесение этого изменения упростит CTE.

DECLARE @tbl TABLE(Id INT,State INT,Quan INT,SellQuan INT,LastId INT)
INSERT INTO @tbl
VALUES
(3,2,5,5,2),
(2,3,10,5,1),
(1,3,15,5,NULL);

;WITH CTE(Id,total,depth)
AS (
SELECT tbl.Id, SellQuan as total, 0 as depth
  FROM @tbl AS tbl
 WHERE tbl.LastId is null
 UNION ALL -- Recursive part of the query
SELECT tbl.Id,
       tbl.SellQuan + CTE.total,
       CTE.depth + 1 as depth
  FROM @tbl AS tbl
 INNER JOIN CTE ON CTE.Id = tbl.LastId
)
SELECT top 1 total
FROM CTE
order by depth desc;

Надеюсь, это поможет.Для получения дополнительной информации о CTE у меня есть несколько статей на моем сайте: http://stevestedman.com/cte/

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