1

나는했습니다이 나무잘못된 결과 트리

  • 나라
    • 지역
      • 도시
        • 협회
          • 센터,451,515,
            • 학교
              • 클래스

,

내가 사용자 ID에 대해이 쿼리를 실행하면 내가 여기이 쿼리

;WITH MyCTE AS 
(
    SELECT T1.ID, UserId, NULL AS PARENT_ID, T1.GroupID, G.EntityLevelID 
    FROM UserJobs T1 
    INNER JOIN [GROUP] G ON T1.GROUPID = G.ID 
    inner join EntityLevel el on G.EntityLevelID = el.Id 
    WHERE T1.UserID = 1 

    UNION ALL 

    SELECT T2.ID, T2.UserId, EL.ParentID, T2.GroupID, G.EntityLevelID 
    FROM UserJobs T2 
    INNER JOIN [GROUP] G ON T2.GROUPID = G.ID 
    inner join EntityLevel el on G.EntityLevelID = el.Id 
    INNER JOIN MyCTE itms ON EL.ParentID >= itms.ID 
) 

SELECT B.*, C.*, A.* 
FROM (SELECT DISTINCT * FROM MyCTE) A 
INNER JOIN [USER] B ON A.UserID = B.ID 
INNER JOIN [Group] C ON A.GroupID = C.ID 
order by a.GroupID ; 

이 = 그 것 1

날 (이 사용자 A = 사용자 ID 아래에있는 모든 사용자를 올바른 데이터를 가져올 수 있습니다 = 1)

1 UserA 1 Country Manager 1 1 1 NULL 1 1 
2 UserB 2 Region Manager 2 2 2 1 2 2 
8 UserH 2 Region Manager 2 8 8 1 2 2 
3 UserC 3 City Manager 3 3 3 2 3 3 
9 UserI 3 City Manager 3 9 9 2 3 3 
4 UserD 4 Association Manager 4 4 4 3 4 4 
10 UserJ 4 Association Manager 4 10 10 3 4 4 
5 UserE 5 Center Manager 5 5 5 4 5 5 
6 UserF 6 School Manager 6 6 6 5 6 6 
7 UserG 7 Teacher 7 7 7 6 7 7 

이 내가 원하는 것을 실제로,하지만 난동일 UserI ID로 사용자를 얻을 필요가있을 때 문제가 온다

9 UserI 3 City Manager 3 9 9 NULL 3 3 

UserI

9 UserI 3 City Manager 3 9 9 NULL 3 3 
    10 UserJ 4 Association Manager 4 10 10 NULL 4 4 

같은 오류가 발생합니다 같은 UserJ

그래서, 결과 필수 보이는 것입니다 그 아래에서 하나의 사용자를 가지고 있기 때문에 그 잘못 : 0

결과는 에서 UserID = 3으로 나와 UserJ을 제공합니다. 트리


스크립트 및 데이터는 여기에 있습니다 : 그것에 대해

CREATE TABLE [dbo].[Assocation](
    [ID] [int] NOT NULL, 
    [Name] [nvarchar](50) NULL, 
    [CityID] [int] NULL, 
CONSTRAINT [PK_Assocation] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 
/****** Object: Table [dbo].[Center] Script Date: 2017-04-04 8:33:43 PM ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[Center](
    [ID] [int] NOT NULL, 
    [Name] [nvarchar](50) NULL, 
    [AssociationID] [int] NULL, 
CONSTRAINT [PK_Center] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 
/****** Object: Table [dbo].[City] Script Date: 2017-04-04 8:33:43 PM ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[City](
    [ID] [int] NOT NULL, 
    [Name] [nvarchar](50) NULL, 
    [RegionID] [int] NULL, 
CONSTRAINT [PK_City] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 
/****** Object: Table [dbo].[Class] Script Date: 2017-04-04 8:33:43 PM ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[Class](
    [ID] [int] NOT NULL, 
    [Name] [nvarchar](50) NULL, 
    [SchoolID] [int] NULL, 
CONSTRAINT [PK_Class] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 
/****** Object: Table [dbo].[Country] Script Date: 2017-04-04 8:33:43 PM ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[Country](
    [ID] [int] NOT NULL, 
    [Name] [nvarchar](50) NULL, 
CONSTRAINT [PK_Country] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 
/****** Object: Table [dbo].[EntityLevel] Script Date: 2017-04-04 8:33:43 PM ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[EntityLevel](
    [ID] [int] NOT NULL, 
    [Name] [nvarchar](50) NULL, 
    [ParentID] [int] NULL, 
CONSTRAINT [PK_Table_1] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 
/****** Object: Table [dbo].[Group] Script Date: 2017-04-04 8:33:43 PM ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[Group](
    [ID] [int] NOT NULL, 
    [Name] [nvarchar](50) NULL, 
    [EntityLevelID] [int] NULL, 
CONSTRAINT [PK_Group] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 
/****** Object: Table [dbo].[Region] Script Date: 2017-04-04 8:33:43 PM ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[Region](
    [ID] [int] NOT NULL, 
    [Name] [nvarchar](50) NULL, 
    [CountryID] [int] NULL, 
CONSTRAINT [PK_Region] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 
/****** Object: Table [dbo].[School] Script Date: 2017-04-04 8:33:43 PM ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[School](
    [ID] [int] NOT NULL, 
    [Name] [nvarchar](50) NULL, 
    [CenterID] [int] NULL, 
CONSTRAINT [PK_School] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 
/****** Object: Table [dbo].[User] Script Date: 2017-04-04 8:33:43 PM ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[User](
    [ID] [int] NOT NULL, 
    [Name] [nvarchar](50) NULL, 
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 
/****** Object: Table [dbo].[UserJobs] Script Date: 2017-04-04 8:33:43 PM ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[UserJobs](
    [ID] [int] NOT NULL, 
    [UserID] [int] NOT NULL, 
    [GroupID] [int] NOT NULL, 
    [EntityID] [int] NOT NULL, 
CONSTRAINT [PK_UserJobs] PRIMARY KEY CLUSTERED 
(
    [ID] ASC, 
    [UserID] ASC, 
    [GroupID] ASC, 
    [EntityID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 
INSERT [dbo].[Assocation] ([ID], [Name], [CityID]) VALUES (1, N'KH', 1) 
GO 
INSERT [dbo].[Assocation] ([ID], [Name], [CityID]) VALUES (2, N'mkh_ass', 2) 
GO 
INSERT [dbo].[Center] ([ID], [Name], [AssociationID]) VALUES (1, N'NorthCenter', 1) 
GO 
INSERT [dbo].[Center] ([ID], [Name], [AssociationID]) VALUES (2, N'SouthCenter', 1) 
GO 
INSERT [dbo].[City] ([ID], [Name], [RegionID]) VALUES (1, N'Jeddah', 1) 
GO 
INSERT [dbo].[City] ([ID], [Name], [RegionID]) VALUES (2, N'MakkahCiry', 1) 
GO 
INSERT [dbo].[Class] ([ID], [Name], [SchoolID]) VALUES (1, N'Class1', 1) 
GO 
INSERT [dbo].[Class] ([ID], [Name], [SchoolID]) VALUES (2, N'Class2', 1) 
GO 
INSERT [dbo].[Class] ([ID], [Name], [SchoolID]) VALUES (3, N'class3', 2) 
GO 
INSERT [dbo].[Class] ([ID], [Name], [SchoolID]) VALUES (4, N'class4', 2) 
GO 
INSERT [dbo].[Country] ([ID], [Name]) VALUES (1, N'KSA') 
GO 
INSERT [dbo].[Country] ([ID], [Name]) VALUES (2, N'UAE') 
GO 
INSERT [dbo].[EntityLevel] ([ID], [Name], [ParentID]) VALUES (1, N'Country', NULL) 
GO 
INSERT [dbo].[EntityLevel] ([ID], [Name], [ParentID]) VALUES (2, N'Region', 1) 
GO 
INSERT [dbo].[EntityLevel] ([ID], [Name], [ParentID]) VALUES (3, N'City', 2) 
GO 
INSERT [dbo].[EntityLevel] ([ID], [Name], [ParentID]) VALUES (4, N'Association', 3) 
GO 
INSERT [dbo].[EntityLevel] ([ID], [Name], [ParentID]) VALUES (5, N'Center', 4) 
GO 
INSERT [dbo].[EntityLevel] ([ID], [Name], [ParentID]) VALUES (6, N'School', 5) 
GO 
INSERT [dbo].[EntityLevel] ([ID], [Name], [ParentID]) VALUES (7, N'Class', 6) 
GO 
INSERT [dbo].[Group] ([ID], [Name], [EntityLevelID]) VALUES (1, N'Country Manager', 1) 
GO 
INSERT [dbo].[Group] ([ID], [Name], [EntityLevelID]) VALUES (2, N'Region Manager', 2) 
GO 
INSERT [dbo].[Group] ([ID], [Name], [EntityLevelID]) VALUES (3, N'City Manager', 3) 
GO 
INSERT [dbo].[Group] ([ID], [Name], [EntityLevelID]) VALUES (4, N'Association Manager', 4) 
GO 
INSERT [dbo].[Group] ([ID], [Name], [EntityLevelID]) VALUES (5, N'Center Manager', 5) 
GO 
INSERT [dbo].[Group] ([ID], [Name], [EntityLevelID]) VALUES (6, N'School Manager', 6) 
GO 
INSERT [dbo].[Group] ([ID], [Name], [EntityLevelID]) VALUES (7, N'Teacher', 7) 
GO 
INSERT [dbo].[Region] ([ID], [Name], [CountryID]) VALUES (1, N'Makkah', 1) 
GO 
INSERT [dbo].[Region] ([ID], [Name], [CountryID]) VALUES (2, N'Riyadh', 1) 
GO 
INSERT [dbo].[School] ([ID], [Name], [CenterID]) VALUES (1, N'School1', 1) 
GO 
INSERT [dbo].[School] ([ID], [Name], [CenterID]) VALUES (2, N'School2', 1) 
GO 
INSERT [dbo].[School] ([ID], [Name], [CenterID]) VALUES (3, N'School3', 2) 
GO 
INSERT [dbo].[User] ([ID], [Name]) VALUES (1, N'UserA') 
GO 
INSERT [dbo].[User] ([ID], [Name]) VALUES (2, N'UserB') 
GO 
INSERT [dbo].[User] ([ID], [Name]) VALUES (3, N'UserC') 
GO 
INSERT [dbo].[User] ([ID], [Name]) VALUES (4, N'UserD') 
GO 
INSERT [dbo].[User] ([ID], [Name]) VALUES (5, N'UserE') 
GO 
INSERT [dbo].[User] ([ID], [Name]) VALUES (6, N'UserF') 
GO 
INSERT [dbo].[User] ([ID], [Name]) VALUES (7, N'UserG') 
GO 
INSERT [dbo].[User] ([ID], [Name]) VALUES (8, N'UserH') 
GO 
INSERT [dbo].[User] ([ID], [Name]) VALUES (9, N'UserI') 
GO 
INSERT [dbo].[User] ([ID], [Name]) VALUES (10, N'UserJ') 
GO 
INSERT [dbo].[UserJobs] ([ID], [UserID], [GroupID], [EntityID]) VALUES (1, 1, 1, 1) 
GO 
INSERT [dbo].[UserJobs] ([ID], [UserID], [GroupID], [EntityID]) VALUES (2, 2, 2, 1) 
GO 
INSERT [dbo].[UserJobs] ([ID], [UserID], [GroupID], [EntityID]) VALUES (3, 3, 3, 1) 
GO 
INSERT [dbo].[UserJobs] ([ID], [UserID], [GroupID], [EntityID]) VALUES (4, 4, 4, 1) 
GO 
INSERT [dbo].[UserJobs] ([ID], [UserID], [GroupID], [EntityID]) VALUES (5, 5, 5, 1) 
GO 
INSERT [dbo].[UserJobs] ([ID], [UserID], [GroupID], [EntityID]) VALUES (6, 6, 6, 1) 
GO 
INSERT [dbo].[UserJobs] ([ID], [UserID], [GroupID], [EntityID]) VALUES (7, 7, 7, 1) 
GO 
INSERT [dbo].[UserJobs] ([ID], [UserID], [GroupID], [EntityID]) VALUES (8, 8, 2, 2) 
GO 
INSERT [dbo].[UserJobs] ([ID], [UserID], [GroupID], [EntityID]) VALUES (9, 9, 3, 2) 
GO 
INSERT [dbo].[UserJobs] ([ID], [UserID], [GroupID], [EntityID]) VALUES (10, 10, 4, 2) 
GO 

모든 솔루션 ...

+0

'PARENT_ID'값이 잘못되었습니다. 특히, UserJ와 UserI는 어떻게 데이터에 링크되어 있습니까? UserJ가 UserI에 링크되어 있거나 UserI가 UserJ와 링크되어 있다는 테이블 및 필드는 무엇입니까? –

+0

@LaughingVergil 그들은 UserJobs And Groups (그룹에있는 entityLevel과 같이)를 통해 서로 연관되어 있으며'UserJ'는'City' 레벨의'UserI'에있는'Association'에 있습니다. – Loai

답변

1

나는 당신의 PARENT_ID 값이 잘못된 것을 반복합니다. 그 이유를 확인하기 위해 UserI (ID = 9) 쿼리를 자세히 살펴 보겠습니다.UserI을 처리 할 때 데이터에 정의

SELECT T1.ID, UserId, NULL AS PARENT_ID, T1.GroupID, G.EntityLevelID 
    FROM #UserJobs T1 
    INNER JOIN #GROUP G ON T1.GROUPID = G.ID 
    inner join #EntityLevel el on G.EntityLevelID = el.Id 
    WHERE T1.UserID = 9 

이것은, 기본 쿼리 될 것이다 (참고 : 나는 테스트 후 정리를 단순화하기 위해 임시 테이블 대신 영구 테이블을 사용)이 쿼리 조각의 출력 모습을 이 :

ID UserId PARENT_ID GroupID EntityLevelID 
9  9 NULL   3  3 

지금까지 문제가 없습니다. 그래서, 당신의 CTE의 재귀 부분은 다음과 같습니다

UNION ALL 

    SELECT T2.ID, T2.UserId, EL.ParentID, T2.GroupID, G.EntityLevelID 
    FROM #UserJobs T2 
    INNER JOIN #GROUP G ON T2.GROUPID = G.ID 
    inner join #EntityLevel el on G.EntityLevelID = el.Id 
    INNER JOIN MyCTE itms 
     ON EL.ParentID >= itms.ID -- <<<< PROBLEM!! 

위에서 보듯이,이 쿼리의 첫 번째 부분에 대한 itms.ID의 값은 [9]. 이 값은 #EntityLevel.ParentID 필드의 값과 조인해야합니다. 그러나 #EntityLevel 테이블에 삽입하는 값을 보면 ParentID 값이 가장 높습니다 [6]. itms.ID 값과 일치하는 레코드가 없으므로 추가 레코드가 링크되지 않습니다.

비슷한 문제는 UserID = 3 레코드와 함께 발생합니다 (이유를 파악하기 위해 쿼리 결과를 조사하십시오).

요약 - 항목을 트리의 다른 항목에 연결하려면 해당 항목 사이에 고유 한 고유 한 링크가 있어야합니다. 특정 고유 링크가 존재하는지 확인해야합니다. 단일 데이터 값일 필요는 없지만 트리가 분기 할 때마다 한 브랜치의 요소는 데이터 값을 기반으로 다른 브랜치의 요소와 식별 할 수 있도록 구분되어야합니다.

+0

감사합니다. 어떻게이 문제를 해결할 수 있다고 생각하니? 아시다시피, 특정 사용자의 모든 사용자를보기 위해이 쿼리를 사용해야하고 나중에 트리에서 특정 지점의 트리를 가져 오는 데 동일한 쿼리를 사용해야합니다. – Loai

+0

다른 테이블 관계에서 또는 사용하지 않는 테이블을 제거하여 필요한 것을 얻을 수 있다고 생각하십니까 – Loai

+0

SQL Server에서 트리를 나타내는 데는 여러 가지 방법이 있습니다. 가장 간단한 방법은 부모 포인터가 실제로 부모 인 레코드, 즉 사용자 수준의 parentID를 가리키는 것입니다. 또 다른 하나는 사용자 당 숫자 범위로 트리를 표현하는 것입니다. 예를 들어 위의 트리를 사용하는 경우처럼 링크를 사용하여 설명하기가 더 쉽습니다. Wikipedia의 [중첩 세트 모델] (https://en.wikipedia.org/wiki/Nested_set_model)을 참조하십시오. 이것은 빠르고 효율적이지만 직관적이지는 않습니다. 일단 그것을 파악하면 매우 효율적입니다. –