【问题标题】:Logic to get filter a list in C# or by stored procedure在 C# 中或通过存储过程过滤列表的逻辑
【发布时间】:2013-04-05 19:48:09
【问题描述】:

假设我的表中有以下数据,其中 Item 的父 ID 为 0。但父级只能有三个子级别/子级。也就是我们需要每个 item 的 parentId = 0,并且每个 parent 最多可以有三个级别的 children。

pkProductID       Name            ParentId 
-------------------------------------------
1                 Cloth              0
2                 T-Shirts           1
3                 Men-Shirts         2
4                 Women-Shirts       2
5                 Kids-Shirts        3
6                 Cosmetics          0
7                 Creams             6
8                 Men-cream          7
9                 Women-Cream        7
10                Kids-cream         9

我们需要包含具有 parentID=0 的项目的列表,然后是 2 个级别的子级,这意味着从上面我只需要这些项目:

1 Cloth
2 T-Shirts
3 Men-Shirts
4 Women-Shirts
6 Cosmetics
7 Creams
8 Men-Cream
9 Women-Cream

【问题讨论】:

  • 您可以在存储过程中使用recursion
  • 需要一些具体细节。请...
  • 请看我的回答。

标签: c# asp.net asp.net-mvc recursion


【解决方案1】:

以下代码应该可以完成工作(相应地更改 tablecolumns 名称):

use [DemoDB]
GO
WITH Emp_CTE AS (
SELECT ProductId, Name, ParentID, 0 as [Level]
FROM [dbo].[Products]
WHERE ParentId = 0
UNION ALL
SELECT p.ProductId, p.Name, p.ParentID, [Level] + 1
FROM [dbo].[Products] as p
INNER JOIN Emp_CTE ecte ON ecte.ProductId = p.ParentID
WHERE [Level] < 2
),
CTE2 AS
(
    SELECT [dbo].[Products].*
    FROM Emp_CTE
        INNER JOIN [dbo].[Products] ON Emp_CTE.ProductId = [dbo].[Products].ParentID
)
SELECT * FROM CTE2

GO

【讨论】:

  • 此解决方案如何确保您最多只能获得 2 个级别的孩子?
  • @marc_s 好点,他应该持有一个变量来计算关卡深度。
  • @marc_s 我更改了代码,以便能够控制递归的深度级别。
  • 这很棒,对我有用,但很难理解。
  • 为“CTE2”多次指定了 Coloum ProductId。上面在执行时抛出了这个错误。这就是我使用您的查询的方式。请告诉我我错在哪里,如果我不包括 CTE2 则可以正常工作
【解决方案2】:

您可以将递归 CTE 用于此类任务,请查看此处显示一个简单示例的链接:http://blog.sqlauthority.com/2008/07/28/sql-server-simple-example-of-recursive-cte/,此处还有另一个示例 http://msdn.microsoft.com/en-us/library/ms186243%28v=sql.105%29.aspx

CREATE TABLE #clothes(
pkProductID INT,
NAME VARCHAR(50),
ParentId INT
)


INSERT  INTO #clothes
        ( pkProductID, NAME, ParentId )
VALUES  ( 1, 'cloth', 0 )

INSERT  INTO #clothes
        ( pkProductID, NAME, ParentId )
VALUES  ( 2, 'tshirt', 1 )

INSERT  INTO #clothes
        ( pkProductID, NAME, ParentId )
VALUES  ( 3, 'mens tshirt', 2 )

INSERT  INTO #clothes
        ( pkProductID, NAME, ParentId )
VALUES  ( 4, 'womens tshirt', 2 )

INSERT  INTO #clothes
        ( pkProductID, NAME, ParentId )
VALUES  ( 5, 'kids tshirt', 3 )

INSERT  INTO #clothes
        ( pkProductID, NAME, ParentId )
VALUES  ( 6, 'cosme', 0 )

INSERT  INTO #clothes
        ( pkProductID, NAME, ParentId )
VALUES  ( 7, 'cream', 6 )

INSERT  INTO #clothes
        ( pkProductID, NAME, ParentId )
VALUES  ( 8, 'm cream', 7 )

INSERT  INTO #clothes
        ( pkProductID, NAME, ParentId )
VALUES  ( 9, 'w cream', 7 )

INSERT  INTO #clothes
        ( pkProductID, NAME, ParentId )
VALUES  ( 10, 'kids cream', 9 )

WITH myCTE AS (
SELECT pkProductID ,
        NAME ,
        ParentId, 0 AS ItemLevel FROM #clothes
        WHERE ParentId = 0

UNION all
SELECT c.pkProductID ,
        c.NAME ,
        c.ParentId, ItemLevel + 1 FROM #clothes c INNER JOIN myCTE mc ON mc.pkProductID = c.ParentId
)
SELECT * FROM   myCTE WHERE ItemLevel <=2 ORDER BY pkProductID

【讨论】:

  • 此解决方案如何确保您最多只能获得 2 个级别的孩子?
  • @marc_s,错过了那部分——我的错!
  • 最新一个 ALTER PROCEDURE [dbo].[Proc_YourPractise] AS BEGIN with Emp_CTE as( select pkProductID,productName,ParentID, 0 as [Level] from products where parentId=0 union ALL SELECT p.pkProductID, p.productName,p.ParentID, [Level] + 1 from products as p inner join Emp_CTE ecte on ecte.pkProductID=p.ParentID where [Level]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-07
  • 2011-11-04
  • 2011-05-28
  • 2022-01-06
  • 1970-01-01
  • 2021-11-18
  • 1970-01-01
相关资源
最近更新 更多