在数据库表中查找循环事务

时间:2014-07-15 09:59:41

标签: sql sql-server database

我在sql server数据库中有一个表,其中存储了事务记录。表包含买方的用户ID和产品卖方的用户ID。我必须在表格中找到圆圈,例如 -

我必须得到类型的记录 - A卖给B,B卖给C,C卖给D和D卖给A。

请帮忙。

4 个答案:

答案 0 :(得分:1)

使用以下功能:

CREATE FUNCTION dbo.CheckIsCircular(@SellerId INT) 
RETURNS BIT
AS BEGIN
    DECLARE @IsCircular BIT = 0
    DECLARE @Sellers TABLE(Id INT)
    DECLARE @TempSellers TABLE(Id INT)
    DECLARE @Buyers TABLE(Id INT)

    INSERT INTO @TempSellers(Id)VALUES(@SellerId)

    WHILE EXISTS(SELECT * FROM @TempSellers)BEGIN
        IF EXISTS(SELECT * 
                  FROM @Sellers s
                  INNER JOIN @TempSellers t ON t.Id = s.Id)BEGIN
            SET @IsCircular = 1
            BREAK;
        END
        INSERT INTO @Sellers(Id)
        SELECT Id FROM @TempSellers

        INSERT INTO @Buyers(Id) SELECT BuyerId FROM YourTable
        DELETE @TempSellers
        INSERT Into @TempSellers(Id)
        SELECT YourTable.SellerId
        FROM YourTable
        INNER JOIN @Buyers ON [@Buyers].Id = YourTable.SellerId
    END

    RETURN @IsCircular
END

答案 1 :(得分:0)

您的问题是图形遍历的挑战;这在SQL中本身不受支持,但您可以simulate it

答案 2 :(得分:0)

这是我在Teradata中执行此操作的框架,因此必须对SQL Server稍微修改语法:

WITH RECURSIVE cte (..., Path, isCycle) AS
(
  SELECT
     ...
    ,',' || CAST(seller AS VARCHAR(1000)) || ',' AS path
    ,0 AS isCycle
  FROM tab
  UNION ALL
  SELECT
      ...
     ,cte.Path || cte.buyer || ',',
     ,case when cte.Path LIKE '%,' || TRIM(tab.buyer) || ',%' then 1 else 0 end
    FROM cte, tab 
      WHERE cte.buyer = tab.seller
      AND cte.isCycle <> 1
)
SELECT ...
   ,Path || Destination
   ,isCycle
FROM cte
WHERE isCycle = 1

在遍历时构建图表的物化路径,并检查下一个买家是否已经在此路径中。

答案 3 :(得分:-1)

使用递归cte

declare @trans table (seller int, buyer int)

insert @trans 
values (1,2),(2,3),(3,4),(4,1),(1,5),(2,6),(3,5)

begin try

;with cte as
(
    select *, convert(varchar(500),'') as route from @trans
    union all
    select cte.seller, t1.buyer, convert(varchar(500),route + CONVERT(varchar(5),t1.seller))  from cte  
        inner join @trans t1 on cte.buyer = t1.seller

) 

    select * from cte
    where seller=buyer
    option (maxrecursion 50)
end try
begin catch
    print 'loops'
end catch