使用 SQL HierarchyID 到 select 分别从 Children 到 Parents
Using SQL HierarchyID to select respectively from Children to Parents
我需要为 return 编写一个存储过程,从 children 到 parents.It 的订单上的一些数据对于描述我想做的事情来说有点复杂,但让我试试它:
假设我们有一个名为 Categories: Parent > Child1 > Child2 > Child3 的层次结构,所有这些都使用 SQL HierarchyID:
存储
Category Table
--------------
Cat_ID | Cat_Name
..............................
/1/ | News
/1/1/ | NewsOfUSA
/1/1/1/ | NewsOfWestUSA
/1/1/1/1/ | NewsOfWashington
我们保存了以下类别的新闻:
News Table
-------------
News_ID | FK_Cat_ID | News_Content
.........................................
0001 | /1/ | one
0002 | /1/1/ | two
0003 | /1/1/1/ | three
0004 | /1/1/1/1/ | four1
0005 | /1/1/1/1/ | four2
0006 | /1/1/1/1/ | four3
0007 | /1/1/1/1/ | four4
最后,我想 select 获得符合以下条件的示例前十条新闻:
If NewsOfWashington has 10 news then select it,
else select from NewsOfWestUSA,
else select from NewsOfUSA,
else select from News,
Until you reach ten
select编辑的顺序是
four4,four3,four2,four1,three,two,one
我尝试过使用递归 CTE,但找不到合适的实现方法。
试试看,它会return按照你想要的顺序排在前10位:
SELECT TOP 10 CASE n.FK_Cat_ID
WHEN '/1/1/1/1/' THEN 0
WHEN '/1/1/1/' THEN 1
WHEN '/1/1/' THEN 2
WHEN '/1/' THEN 3
Else 4 END,*
FROM News as n
INNER JOIN Category as c
ON n.FK_Cat_ID = c.Cat_ID
ORDER BY 1;
要确定距离,查找所有后代,然后按深度差异排序:
USE tempdb;
CREATE TABLE Categories (CatID hierarchyid not null primary key, Name nvarchar(255) not null);
CREATE TABLE News (NewsID int not null primary key, CatID hierarchyid not null, NewsContent nvarchar(max) not null);
INSERT INTO Categories
VALUES ('/1/', 'News'),
('/1/1/', 'NewsOfUSA'),
('/1/1/1/', 'NewsOfIndiana'),
('/1/2/', 'NewsOfUK');
INSERT INTO News
VALUES (1, '/1/', 'Aliens invaded'),
(2, '/1/1/', 'Aliens invaded the US'),
(3, '/1/1/1/', 'Aliens invaded the midwest'),
(4, '/1/2/', 'Aliens invaded the UK');
DECLARE @VisitorLocation hierarchyid = '/1/1/1/';
WITH
relevantCategories AS (
SELECT c.*, ABS(@VisitorLocation.GetLevel() - c.CatID.GetLevel()) as RelevanceDistance
FROM Categories c
WHERE @VisitorLocation.IsDescendantOf(c.CatID) = 1
)
SELECT TOP(10) n.*, c.RelevanceDistance
FROM relevantCategories c
INNER JOIN News n on n.CatID = c.CatID
ORDER BY RelevanceDistance ASC, n.NewsID DESC;
DROP TABLE Categories;
DROP TABLE News;
产生:
NewsID CatID NewsContent RelevanceDistance
-------- -------- ---------------------------- -------------------
3 0x5AD6 Aliens invaded the midwest 0
2 0x5AC0 Aliens invaded the US 1
1 0x58 Aliens invaded 2
完全从 Mitch 的回答中窃取数据脚本,这还不错:
CREATE TABLE Categories
(
CatID hierarchyid not null
primary key ,
Name nvarchar(255) not null
);
CREATE TABLE News
(
NewsID int not null
primary key ,
CatID hierarchyid not null ,
NewsContent nvarchar(max) not null
);
INSERT INTO Categories
VALUES ('/1/', 'News'),
('/1/1/', 'NewsOfUSA'),
('/1/1/1/', 'NewsOfIndiana'),
('/1/2/', 'NewsOfUK');
INSERT INTO News
VALUES (1, '/1/', 'Aliens invaded'),
(2, '/1/1/', 'Aliens invaded the US'),
(3, '/1/1/1/', 'Aliens invaded the midwest'),
(4, '/1/2/', 'Aliens invaded the UK');
-- actual answer begins here
select TOP(10) News.[NewsContent]
from dbo.Categories as parent
join dbo.Categories as child
on child.CatID.IsDescendantOf(parent.CatID) = 1
join News
on News.CatID = parent.CatID
WHERE child.Name = 'NewsOfIndiana'
order by News.CatID.GetLevel() DESC
本质上,我使用 IsDescendentOf()
方法来获取给定类别属于哪些类别,然后根据新的类别列表加入新闻项目,最后对 GetLevel()
方法(returns 给定值在层次结构中的深度)。
我需要为 return 编写一个存储过程,从 children 到 parents.It 的订单上的一些数据对于描述我想做的事情来说有点复杂,但让我试试它: 假设我们有一个名为 Categories: Parent > Child1 > Child2 > Child3 的层次结构,所有这些都使用 SQL HierarchyID:
存储Category Table
--------------
Cat_ID | Cat_Name
..............................
/1/ | News
/1/1/ | NewsOfUSA
/1/1/1/ | NewsOfWestUSA
/1/1/1/1/ | NewsOfWashington
我们保存了以下类别的新闻:
News Table
-------------
News_ID | FK_Cat_ID | News_Content
.........................................
0001 | /1/ | one
0002 | /1/1/ | two
0003 | /1/1/1/ | three
0004 | /1/1/1/1/ | four1
0005 | /1/1/1/1/ | four2
0006 | /1/1/1/1/ | four3
0007 | /1/1/1/1/ | four4
最后,我想 select 获得符合以下条件的示例前十条新闻:
If NewsOfWashington has 10 news then select it, else select from NewsOfWestUSA, else select from NewsOfUSA, else select from News, Until you reach ten
select编辑的顺序是
four4,four3,four2,four1,three,two,one
我尝试过使用递归 CTE,但找不到合适的实现方法。
试试看,它会return按照你想要的顺序排在前10位:
SELECT TOP 10 CASE n.FK_Cat_ID
WHEN '/1/1/1/1/' THEN 0
WHEN '/1/1/1/' THEN 1
WHEN '/1/1/' THEN 2
WHEN '/1/' THEN 3
Else 4 END,*
FROM News as n
INNER JOIN Category as c
ON n.FK_Cat_ID = c.Cat_ID
ORDER BY 1;
要确定距离,查找所有后代,然后按深度差异排序:
USE tempdb;
CREATE TABLE Categories (CatID hierarchyid not null primary key, Name nvarchar(255) not null);
CREATE TABLE News (NewsID int not null primary key, CatID hierarchyid not null, NewsContent nvarchar(max) not null);
INSERT INTO Categories
VALUES ('/1/', 'News'),
('/1/1/', 'NewsOfUSA'),
('/1/1/1/', 'NewsOfIndiana'),
('/1/2/', 'NewsOfUK');
INSERT INTO News
VALUES (1, '/1/', 'Aliens invaded'),
(2, '/1/1/', 'Aliens invaded the US'),
(3, '/1/1/1/', 'Aliens invaded the midwest'),
(4, '/1/2/', 'Aliens invaded the UK');
DECLARE @VisitorLocation hierarchyid = '/1/1/1/';
WITH
relevantCategories AS (
SELECT c.*, ABS(@VisitorLocation.GetLevel() - c.CatID.GetLevel()) as RelevanceDistance
FROM Categories c
WHERE @VisitorLocation.IsDescendantOf(c.CatID) = 1
)
SELECT TOP(10) n.*, c.RelevanceDistance
FROM relevantCategories c
INNER JOIN News n on n.CatID = c.CatID
ORDER BY RelevanceDistance ASC, n.NewsID DESC;
DROP TABLE Categories;
DROP TABLE News;
产生:
NewsID CatID NewsContent RelevanceDistance
-------- -------- ---------------------------- -------------------
3 0x5AD6 Aliens invaded the midwest 0
2 0x5AC0 Aliens invaded the US 1
1 0x58 Aliens invaded 2
完全从 Mitch 的回答中窃取数据脚本,这还不错:
CREATE TABLE Categories
(
CatID hierarchyid not null
primary key ,
Name nvarchar(255) not null
);
CREATE TABLE News
(
NewsID int not null
primary key ,
CatID hierarchyid not null ,
NewsContent nvarchar(max) not null
);
INSERT INTO Categories
VALUES ('/1/', 'News'),
('/1/1/', 'NewsOfUSA'),
('/1/1/1/', 'NewsOfIndiana'),
('/1/2/', 'NewsOfUK');
INSERT INTO News
VALUES (1, '/1/', 'Aliens invaded'),
(2, '/1/1/', 'Aliens invaded the US'),
(3, '/1/1/1/', 'Aliens invaded the midwest'),
(4, '/1/2/', 'Aliens invaded the UK');
-- actual answer begins here
select TOP(10) News.[NewsContent]
from dbo.Categories as parent
join dbo.Categories as child
on child.CatID.IsDescendantOf(parent.CatID) = 1
join News
on News.CatID = parent.CatID
WHERE child.Name = 'NewsOfIndiana'
order by News.CatID.GetLevel() DESC
本质上,我使用 IsDescendentOf()
方法来获取给定类别属于哪些类别,然后根据新的类别列表加入新闻项目,最后对 GetLevel()
方法(returns 给定值在层次结构中的深度)。