[最初的帖子的道歉,没有创建表的DDL / DML语句-现在已修复]
我正在创建一个数据库,该数据库实质上记录了本地设施的检查结果。如果“检查”可以识别出故障,则有时可能导致“案件”被提出。案件也可以在没有检查的情况下提出,例如,如果有公众投诉。一项检查可能导致举起一个以上的案件-例如,如果该设施是一个本地公园,则可能是由于一项检查而引起的案件是(a)割草不良和(b)垃圾箱未被清空。
一个案例不能导致检查,但可能导致进一步的案例,因此在我的“案例”表中,我有DerivedFromInspectionID和DerivedFromCaseID列。
有两个表:检查表和GMCase(用于“地面维护案例”记录)
可以如下创建表的显着部分:
CREATE TABLE [Inspection](
[InspectionID] [int] NOT NULL PRIMARY KEY,
[InspectionDate] [datetime] NULL,
[InspectionType] [varchar](10) NULL
)
CREATE TABLE [GMCase](
[CaseID] [int] NOT NULL PRIMARY KEY,
[CaseDate] [datetime] NULL,
[CaseType] [varchar](20) NULL,
[DerivedFromCaseID] [int] NULL CONSTRAINT fk_Case_Case FOREIGN KEY REFERENCES GMCase (CaseID),
[DerivedFromInspectionID] [int] NULL CONSTRAINT fk_Case_Inspection FOREIGN KEY REFERENCES Inspection(InspectionID)
)
INSERT INTO Inspection(InspectionID, InspectionDate,InspectionType)
VALUES
(2,GETDATE(),'Scheduled'),
(3,GETDATE(),'Scheduled'),
(5,GETDATE(),'Ad-hoc')
INSERT INTO GMCase (CaseID,CaseDate,CaseType,DerivedFromCaseID,DerivedFromInspectionID)
VALUES
(1 , GETDATE(),'Compliment',NULL,NULL),
(2, GETDATE(),'Complaint',NULL,2),
(3,GETDATE(),'Instruction',2,NULL),
(5,GETDATE(),'Rectification',3,NULL),
(14,GETDATE(),'Complaint',NULL,2)
我想创建一个显示
链的视图[Inspection1] (Optionally)
>>> Case1
>>> Case2
>>> Case3.
当查看“案例”或“检查”详细信息时,将在数据库应用程序中使用它。
在应用程序中,我需要能够查看链中的任何情况,并查看其如何适合该链。因此,如果我看一下Case2,它应该显示上面的所有项目。
为了获取源数据,我最初创建了一个包含UNION查询的视图,以将Inspection和GMCase表中的等效列组合在一起。由于我需要能够识别每个案例/检查,因此我将CaseID和InspectionID引入到了最初的两个单独的列中,但是我认为只有一个ID列会很有用。我想确保此ID上没有明显的重复(在Inspection 2中包含2,在Case2中也包含2),因此我想到了将ID如果是InspectionID设为负数的想法(也许这是一个错误吗?)< / p>
我添加了一个“级别”列,以帮助确定案件是在根级别还是从检查派生,并作为CTE中级别计算的起点。
我还添加了一个名为RootCase的列,对于“检查”,该列使我可以查看记录有链接到“检查”的GMCase(如果有)。举例来说,这是为了让我看一下案例3,我可以看到它最终源自检查2,因为它的根本原因与检查2的RootCase相同。如果这是一个错误...
该视图的SQL如下:
CREATE VIEW vwCaseHierarchySource
AS
SELECT CaseID,
CaseDate,
CaseType,
ISNULL(-g.DerivedFromInspectionID,g.DerivedFromCaseID) AS ParentCaseID,
CASE WHEN g.DerivedFromCaseID IS NULL AND g.DerivedFromInspectionID IS NULL THEN 0 ELSE 1 END AS [Level],
CaseID AS RootCase
FROM GMCase g
UNION
SELECT -i.InspectionID
,i.InspectionDate
,CONVERT(VARCHAR(20),i.InspectionType + ' inspection') AS CaseType
,NULL AS ParentCaseID
,CASE WHEN g.CaseID IS NULL THEN 0 ELSE 1 END AS [Level]
,g.CaseID AS RootCase
FROM Inspection i
LEFT JOIN GMCase g
ON i.InspectionID = g.DerivedFromInspectionID
然后,我尝试了多种创建CTE的方法来显示此层次结构。 CTE不是我的专长,我记不住我尝试过的所有内容,但是下面是我目前的工作。
我怀疑我的问题是,由于检查可能导致(在我的样本数据中确实)导致不止一种情况,因为每当我使用CTE时,我都会获得正确的信息,但是还有不正确的信息。如果我尝试获取案例2的结果,那么我将获得案例2的层次结构,还可以获得案例14的行。如果我尝试对案例14,那么我将获得该结果,以及案例2的所有行。>
这是CTE:
CREATE VIEW [dbo].[vwCaseInspectionHierarchy]
AS
WITH CaseList AS
(
SELECT
CaseID,
CaseDate,
CaseType,
ParentCaseID,
RootCase,
RootCase.[Level]
FROM vwCaseHierarchySource RootCase
WHERE RootCase.ParentCaseID IS NULL
UNION ALL
SELECT
ChildCase.CaseID,
ChildCase.CaseDate,
ChildCase.CaseType,
ChildCase.ParentCaseID,
CaseList.RootCase,
CaseList.[Level]+1
FROM vwCaseHierarchySource ChildCase
INNER JOIN CaseList ON
ChildCase.ParentCaseID=CaseList.CaseID
)
SELECT *
,REPLICATE(' ',[Level]*5) + CaseType AS IndentedCaseType
FROM CaseList
我的代码对其进行测试:
SELECT *
FROM [vwCaseInspectionHierarchy]
WHERE RootCase=2
有人可以帮助我吗?抱歉,发表了很长的文章,但希望我已经包括了所有相关内容...
安德鲁
答案 0 :(得分:1)
我认为您实际上不需要这种观点。
只需对表本身进行递归CTE即可解决问题。
您可以在两个表中使用类型字符串作为递归种子。
示例代码段:
declare @Inspection table (InspectionID int primary key, InspectionDate datetime, InspectionType varchar(30));
declare @GMCase table (CaseID int primary key, CaseDate date, CaseType varchar(30), DerivedFromCaseID int, DerivedFromInspectionID int);
insert into @Inspection (InspectionID, InspectionDate, InspectionType) values
(102, '2019-01-22 00:00:00.000', 'Scheduled'),
(103, '2019-02-06 14:25:55.133', 'Scheduled'),
(105, '2019-02-06 16:59:04.820', 'Ad-hoc');
insert into @GMCase (CaseID, CaseDate, CaseType, DerivedFromCaseID, DerivedFromInspectionID) values
(1, '2019-01-23', 'Compliment', NULL, NULL),
(2, '2018-12-04', 'Complaint', NULL, 102),
(3, '2018-12-04', 'Instruction', 2, NULL),
(5, '2018-12-21', 'Rectification', 3, NULL),
(14, '2019-02-06', 'Complaint', NULL, 2),
(15, '2019-02-07', 'Compliment', NULL, NULL),
(16, '2019-02-08', 'Complaint', 15, NULL);
with RCTE as
(
-- Seeding the recursive CTE
select i.InspectionID, n as Lvl, t.CaseID as RootCaseID, case when n = 1 then t.CaseID end as CaseID, t.DerivedFromCaseID, iif(n=0, i.InspectionType, t.CaseType) as [Type]
from @GMCase t
left join @Inspection i ON i.InspectionID = t.DerivedFromInspectionID
cross join (values (0),(1)) nums(n)
where t.DerivedFromCaseID is null
union all
select r.InspectionID, r.Lvl + 1, r.RootCaseID, t.CaseID, t.DerivedFromCaseID, t.CaseType
from RCTE r
join @GMCase t on t.DerivedFromCaseID = r.CaseID
)
select c.RootCaseID, c.CaseID, c.InspectionID, t.CaseDate,
concat(replicate(' ',c.Lvl*5),COALESCE([Type],'Inspection')) AS IndentedType
from RCTE c
left join @GMCase t on t.CaseID = c.CaseID
order by c.RootCaseID, c.Lvl;
结果:
RootCaseID CaseID InspectionID CaseDate IndentedType
1 NULL NULL NULL Inspection
1 1 NULL 2019-01-23 Compliment
2 NULL 102 NULL Scheduled
2 2 102 2018-12-04 Complaint
2 3 102 2018-12-04 Instruction
2 5 102 2018-12-21 Rectification
14 NULL NULL NULL Inspection
14 14 NULL 2019-02-06 Complaint
15 NULL NULL NULL Inspection
15 15 NULL 2019-02-07 Compliment
15 16 NULL 2019-02-08 Complaint