我为长期的问题描述道歉,但我无法将其分解为更多。 在继续阅读之前,请记住我的最终目标是T-SQL(可能是一些递归CTE?)。然而,在正确的方向上的推动将非常受欢迎(我已经尝试了一百万件事情并且已经抓了几个小时)。
考虑以下问题:我有一个类别表,通过ParentCategoryID-> CategoryID自我引用:
----------------------- | Category | ----------------------- | *CategoryID | | Name | | ParentCategoryID | -----------------------
这种类型的表允许我构建一个树结构,比如说:
----------------- | parentCategory| ----------------- / | \ child(1) child child / \ child(2) child(3)
其中“孩子”的意思是“孩子类别”(忽略这些数字,我稍后会解释)。显然,我可以在任何级别拥有尽可能多的孩子。
我每天编写的程序都会将值存储到“ValueRegistration”表中,该表连接到“Category”,如下所示:
------------------------ ---------------------- ---------------------- | ValueRegistration | | Item | | Category | ------------------------ ---------------------- ---------------------- | *RegID | | *ItemID | | *CategoryID | | Date |>-------| CategoryID |>---------| Name | | ItemID | | ItemTypeID | | ParentCategoryID | | Value | ---------------------- ---------------------- ------------------------ Y | | --------------------- | ItemType | --------------------- | *ItemTypeID | | ItemType | ---------------------
如您所见,ValueRegistration涉及特定的项目,而该项目又属于某个类别。该类别可能有也可能没有父母(以及祖父母和曾祖父母等)。例如,它可能是上面所示的树中左下角(数字2)的孩子。此外,Item是某个ItemType。
我的目标:
我每天将值注册到ValueRegistration表(换句话说,Date和ItemID组合也是主键)。我希望能够在以下表单中检索结果集:
[ValueRegistration.Date, ItemType.ItemTypeID, Category.CategoryID, Value]
这看起来很简单(显然只是一堆连接)。但是,我还想要在ValueRegistration表中实际不存在的行的结果,即结果,其中给定日期和itemID的兄弟节点的值相加,并且生成新行 ValueRegistration.Date 和 ItemType.ItemTypeID 与子节点中的相同,但 CategoryID 是子节点的父节点。请记住,结果集中此类行不存在Item。
例如,考虑一个场景,我在一堆日期和一堆ItemID上有子2和3的ValueRegistrations。显然,每个注册属于某个ItemType和Category。读者应该清楚
ValueRegistration.Date, ItemType.ItemTypeID, Category.CategoryID
是一个足以识别特定ValueRegistration的键(换句话说,它可以在不创建临时Item行的情况下解决我的问题),因此我可以内连接所有表,例如,以下结果:< / p>
ValueReg.Date, ItemType.ItemTypeID, Category.CategoryID, ValueReg.Value
08-mar-2013, 1, 5, 200
08-mar-2013, 1, 6, 250
现在假设我有四个类别行,如下所示:
1, category1, NULL
2, category2, 1
5, category5, 2
6, category6, 2
即。类别1是类别2的父类,类别2是类别5和类别6的父类别。类别1没有父类。我现在希望将以下行追加到结果集中:
08-mar-2013, 1, 2, (200+250)
08-mar-2013, 1, 1, (200+250+sum(values in all other childnodes of node 1)
记住:
我试图按照this的方式设置一些内容,但我似乎不得不按日期和ItemTypeID进行分组,这在CTE中是不允许的。我的程序员只想创建一个递归函数,但我真的很难在SQL中做到这一点。
任何人都知道从哪里开始,我应该尝试什么,甚至(手指交叉)解决方案?
谢谢!
亚历山大
编辑: SQL FIDDLE
CREATE TABLE ItemType(
ItemTypeID INT PRIMARY KEY,
ItemType VARCHAR(50)
);
CREATE TABLE Category(
CategoryID INT PRIMARY KEY,
Name VARCHAR(50),
ParentCategoryID INT,
FOREIGN KEY(ParentCategoryID) REFERENCES Category(CategoryID)
);
CREATE TABLE Item(
ItemID INT PRIMARY KEY,
CategoryID INT NOT NULL,
ItemTypeID INT NOT NULL,
FOREIGN KEY(CategoryID) REFERENCES Category(CategoryID),
FOREIGN KEY(ItemTypeID) REFERENCES ItemType(ItemTypeID)
);
CREATE TABLE ValueRegistration(
RegID INT PRIMARY KEY,
Date DATE NOT NULL,
Value INT NOT NULL,
ItemID INT NOT NULL,
FOREIGN KEY(ItemID) REFERENCES Item(ItemID)
);
INSERT INTO ItemType VALUES(1, 'ItemType1');
INSERT INTO ItemType VALUES(2, 'ItemType2');
INSERT INTO Category VALUES(1, 'Category1', NULL); -- Top parent (1)
INSERT INTO Category VALUES(2, 'Category2', 1); -- A child of 1
INSERT INTO Category VALUES(3, 'Category3', 1); -- A child of 1
INSERT INTO Category VALUES(4, 'Category4', 2); -- A child of 2
INSERT INTO Category VALUES(5, 'Category5', 2); -- A child of 2
INSERT INTO Category VALUES(6, 'Category6', NULL); -- Another top parent
INSERT INTO Item VALUES(1, 4, 1); -- Category 4, ItemType 1
INSERT INTO Item VALUES(2, 5, 1); -- Category 5, ItemType 1
INSERT INTO Item VALUES(3, 3, 1); -- Category 3, ItemType 1
INSERT INTO Item VALUES(4, 1, 2); -- Category 1, ItemType 2
INSERT INTO ValueRegistration VALUES(1, '2013-03-08', 100, 1);
INSERT INTO ValueRegistration VALUES(2, '2013-03-08', 200, 2);
INSERT INTO ValueRegistration VALUES(3, '2013-03-08', 300, 3);
INSERT INTO ValueRegistration VALUES(4, '2013-03-08', 400, 4);
INSERT INTO ValueRegistration VALUES(5, '2013-03-09', 120, 1);
INSERT INTO ValueRegistration VALUES(6, '2013-03-09', 220, 2);
INSERT INTO ValueRegistration VALUES(7, '2013-03-09', 320, 3);
INSERT INTO ValueRegistration VALUES(8, '2013-03-09', 420, 4);
-- -------------------- RESULTSET I WANT ----------------------
-- vr.Date | ItemType | CategoryTypeID | Value
-- ------------------------------------------------------------
-- 2013-03-08 | 'ItemType1' | 'Category4' | 100 Directly available
-- 2013-03-08 | 'ItemType1' | 'Category5' | 200 Directly available
-- 2013-03-08 | 'ItemType1' | 'Category3' | 300 Directly available
-- 2013-03-08 | 'ItemType1' | 'Category2' | 100+200 Calculated tree node
-- 2013-03-08 | 'ItemType1' | 'Category1' | 100+200+300 Calculated tree node
-- 2013-03-08 | 'ItemType2' | 'Category1' | 400 Directly available
-- 2013-03-09 | 'ItemType1' | 'Category4' | 120 Directly available
-- 2013-03-09 | 'ItemType1' | 'Category5' | 220 Directly available
-- 2013-03-09 | 'ItemType1' | 'Category3' | 320 Directly available
-- 2013-03-09 | 'ItemType1' | 'Category2' | 120+220 Calculated tree node
-- 2013-03-09 | 'ItemType1' | 'Category1' | 120+220+320 Calculated tree node
-- 2013-03-09 | 'ItemType2' | 'Category1' | 420 Directly available
答案 0 :(得分:1)
如果将所有连接替换为具有此动态关系的连接的表类别,您将获得您正在寻找的层次结构:
with Category as (
select * from ( values
(1,'Fred',null),
(2,'Joan',1),
(3,'Greg',2),
(4,'Jack',2),
(5,'Jill',4),
(6,'Bill',3),
(7,'Sam',6)
) Category(CategoryID,Name,ParentCategoryID)
)
, Hierarchy as (
select 0 as [Level],* from Category
-- where Parent is null
union all
select super.[Level]+1, sub.CategoryID, super.Name, super.ParentCategoryID
from Category as sub
join Hierarchy as super on super.CategoryID = sub.ParentCategoryID and sub.ParentCategoryID is not null
)
select * from Hierarchy
-- where CategoryID = 6
-- order by [Level], CategoryID
例如,取消注释底部的两行将产生此结果集:
Level CategoryID Name ParentCategoryID
----------- ----------- ---- ----------------
0 6 Bill 3
1 6 Greg 2
2 6 Joan 1
3 6 Fred NULL