感谢您抽出宝贵时间阅读本文,非常感谢所有帮助。
我需要帮助创建一个SQL查询,该查询返回匹配或包含描述的WHERE查询字符串的项目的所有祖先和后代。
我的桌子是这样的:
ID Hierarchy Name 1 / Products 2 /1/ Cars 3 /1/1/ Red 4 /1/2/ Blue 5 /2/ Bike 6 /2/1/ Green 7 /2/2/ Red
我想通过描述进行搜索,所有匹配都应该与他们的后代和祖先一起返回。
e.g。搜索字词='红色'
结果
ID Hierarchy Name 1 / Products 2 /1/ Cars 3 /1/1/ Red 5 /2/ Bike 7 /2/2/ Red
另一个例子:
搜索字词=' bi'
结果(因为bi包含在自行车字符串
中ID Hierarchy Name 1 / Products 5 /2/ Bike 6 /2/1/ Green 7 /2/2/ Red
非常感谢,
罗布
的 的 ** * ** * ** * 的* 编辑28-Mar-14 * ** * ** * ****
我差点遇到以下问题。但是它只检索所有祖先而不是后代。
WITH Ancestors(Hierarchy, [Name], AncestorId) AS ( SELECT Hierarchy, [Name], Hierarchy.GetAncestor(1) FROM dbo.SpecProducts WHERE Name = 'Chrome' -- or whatever you need to select that node UNION ALL SELECT ht.Hierarchy, ht.[Name], ht.Hierarchy.GetAncestor(1) FROM dbo.SpecProducts ht INNER JOIN Ancestors a ON ht.Hierarchy = a.AncestorId ) SELECT DISTINCT *, Hierarchy.ToString() FROM Ancestors
** * *** 编辑07- 3月14日 ** * ** * ** * ** < EM> * *
@Yousseff DAOUI - 在回答您的回答时,我很难将您的代码转换为使用我的表格。以下是我尝试使用我的表格编写代码:
DECLARE @p_name NVARCHAR = 'Gr'; WITH Temp AS (SELECT * FROM SpecProducts) -- DB Table ,Temp_parents AS ( SELECT ID, Hierarchy, Name --, 0 _Level FROM Temp WHERE Name LIKE '%'+@p_name+'%' UNION ALL SELECT tab.ID, tab.Hierarchy, tab.Name --, p._Level+1 FROM Temp tab INNER JOIN Temp_parents p ON p.Hierarchy LIKE tab.Hierarchy+'_/') ,Temp_descendants AS ( SELECT ID, Hierarchy, Name --, 0 _Level FROM Temp WHERE Name LIKE '%'+@p_name+'%' UNION ALL SELECT tab.ID, tab.Hierarchy, tab.Name --, d._Level-1 FROM Temp tab INNER JOIN Temp_descendants d ON tab.Hierarchy LIKE d.Hierarchy+'_/') SELECT * FROM Temp_parents UNION SELECT * FROM Temp_descendants
注意第3行如何尝试从名为SpecProducts的表中提取数据:
WITH Temp AS (SELECT * FROM SpecProducts) -- DB Table
但是,当我尝试执行代码时,MS SQL Server Management Studio会继续输出以下错误:
消息403,级别16,状态1,行3 数据类型的运算符无效。运算符等于add,类型等于hierarchyid。
你知道我怎么能让它发挥作用吗?
非常感谢。
** 第二次编辑 - 07年3月7日 * < / p>
这看起来好一点,但查询真的很慢(我认为它会拉出比它应该更多的行)。是因为HierarchyID&#39; /&#39;正在返回,然后找到根的所有孩子&#39; /&#39;,这就是一切?
DECLARE @p_name NVARCHAR = 'wallpaper'; WITH Temp AS (SELECT * FROM SpecProducts) -- DB Table ,Temp_parents AS ( SELECT ID, Hierarchy, Name --, 0 _Level FROM Temp WHERE Name LIKE '%'+@p_name+'%' UNION ALL SELECT tab.ID, tab.Hierarchy, tab.Name --, p._Level+1 FROM Temp tab INNER JOIN Temp_parents p ON p.Hierarchy.ToString() LIKE tab.Hierarchy.ToString()+'_/') ,Temp_descendants AS ( SELECT ID, Hierarchy, Name --, 0 _Level FROM Temp WHERE Name LIKE '%'+@p_name+'%' UNION ALL SELECT tab.ID, tab.Hierarchy, tab.Name --, d._Level-1 FROM Temp tab INNER JOIN Temp_descendants d ON tab.Hierarchy.ToString() LIKE d.Hierarchy.ToString()+'_/') SELECT * FROM Temp_parents UNION SELECT * FROM Temp_descendants
** * ** 第3次编辑 - 07年3月7日 * ** * ** *
好的,非常抱歉编辑次数。但现在这似乎是基于优素福的代码。
DECLARE @p_name NVARCHAR(255) = 'natural'; WITH Temp_parents AS ( SELECT ID, Hierarchy, Name --, 0 _Level FROM SpecProducts WHERE Name LIKE '%'+@p_name+'%' UNION ALL SELECT tab.ID, tab.Hierarchy, tab.Name --, p._Level+1 FROM SpecProducts tab INNER JOIN Temp_parents p ON p.Hierarchy.ToString() LIKE tab.Hierarchy.ToString()+'_/') ,Temp_descendants AS ( SELECT ID, Hierarchy, Name --, 0 _Level FROM SpecProducts WHERE Name LIKE '%'+@p_name+'%' UNION ALL SELECT tab.ID, tab.Hierarchy, tab.Name --, d._Level-1 FROM SpecProducts tab INNER JOIN Temp_descendants d ON tab.Hierarchy.ToString() LIKE d.Hierarchy.ToString()+'_/') SELECT * FROM Temp_parents UNION SELECT * FROM Temp_descendants
答案 0 :(得分:1)
已经为您找到了解决方案,我希望它能为您提供帮助,以下是代码:
DECLARE @p_name NVARCHAR(255) = 'b'
IF OBJECT_ID('Temp') IS NOT NULL
DROP TABLE Temp
IF OBJECT_ID('Temp_parents') IS NOT NULL
DROP TABLE Temp_parents
IF OBJECT_ID('Temp_descendants') IS NOT NULL
DROP TABLE Temp_descendants
SELECT *
INTO Temp
FROM (
SELECT 1 AS ID, '/' AS Hierarchy, 'Products' Name UNION ALL
SELECT 2 AS ID, '/1/' AS Hierarchy, 'Cars' Name UNION ALL
SELECT 3 AS ID, '/1/1/' AS Hierarchy, 'Red' Name UNION ALL
SELECT 4 AS ID, '/1/2/' AS Hierarchy, 'Blue' Name UNION ALL
SELECT 5 AS ID, '/2/' AS Hierarchy, 'Bike' Name UNION ALL
SELECT 6 AS ID, '/2/1/' AS Hierarchy, 'Green' Name UNION ALL
SELECT 7 AS ID, '/2/2/' AS Hierarchy, 'Red' Name) AS T
DECLARE @v_name_1 NVARCHAR(255)= @p_name;
WITH parents AS (
SELECT ID, Hierarchy, Name, 0 _Level
FROM
Temp
WHERE
Name LIKE '%'+@v_name_1+'%'
UNION ALL
SELECT tab.ID, tab.Hierarchy, tab.Name, p._Level+1
FROM
Temp tab
INNER JOIN
parents p
ON p.Hierarchy LIKE tab.Hierarchy+'_/')
select ID, Hierarchy, Name
INTO Temp_parents
from parents
DECLARE @v_name_2 NVARCHAR(255)= @p_name;
WITH descendants AS (
SELECT ID, Hierarchy, Name, 0 _Level
FROM
Temp
WHERE
Name LIKE '%'+@v_name_2+'%'
UNION ALL
SELECT tab.ID, tab.Hierarchy, tab.Name, d._Level-1
FROM
Temp tab
INNER JOIN
descendants d
ON tab.Hierarchy LIKE d.Hierarchy+'_/')
SELECT ID,Hierarchy ,Name
INTO Temp_descendants
FROM
descendants
WHERE
ID IS NOT NULL
SELECT *
FROM Temp_parents
UNION
SELECT *
FROM Temp_descendants
IF OBJECT_ID('Temp') IS NOT NULL
DROP TABLE Temp
IF OBJECT_ID('Temp_parents') IS NOT NULL
DROP TABLE Temp_parents
IF OBJECT_ID('Temp_descendants') IS NOT NULL
DROP TABLE Temp_descendants
祝你好运:)
答案 1 :(得分:1)
这是另一种基于第一种方式编写代码的方法,使代码看起来更容易:)
DECLARE @p_name NVARCHAR(255) = 'Gr';
WITH Temp AS (
SELECT 1 AS ID, '/' AS Hierarchy, 'Products' Name UNION ALL
SELECT 2 AS ID, '/1/' AS Hierarchy, 'Cars' Name UNION ALL
SELECT 3 AS ID, '/1/1/' AS Hierarchy, 'Red' Name UNION ALL
SELECT 4 AS ID, '/1/2/' AS Hierarchy, 'Blue' Name UNION ALL
SELECT 5 AS ID, '/2/' AS Hierarchy, 'Bike' Name UNION ALL
SELECT 6 AS ID, '/2/1/' AS Hierarchy, 'Green' Name UNION ALL
SELECT 7 AS ID, '/2/2/' AS Hierarchy, 'Red' Name)
,Temp_parents AS (
SELECT ID, Hierarchy, Name --, 0 _Level
FROM
Temp
WHERE
Name LIKE '%'+@p_name+'%'
UNION ALL
SELECT tab.ID, tab.Hierarchy, tab.Name --, p._Level+1
FROM
Temp tab
INNER JOIN
Temp_parents p
ON p.Hierarchy LIKE tab.Hierarchy+'_/')
,Temp_descendants AS (
SELECT ID, Hierarchy, Name --, 0 _Level
FROM
Temp
WHERE
Name LIKE '%'+@p_name+'%'
UNION ALL
SELECT tab.ID, tab.Hierarchy, tab.Name --, d._Level-1
FROM
Temp tab
INNER JOIN
Temp_descendants d
ON tab.Hierarchy LIKE d.Hierarchy+'_/')
SELECT *
FROM Temp_parents
UNION
SELECT *
FROM Temp_descendants
祝你好运
编辑07-Mar-14 - 为了使用我的桌子,我必须将其修改为以下内容 - 现在看起来效果很好** 强>
DECLARE @p_name NVARCHAR(255) = 'natural'; WITH Temp_parents AS ( SELECT ID, Hierarchy, Name --, 0 _Level FROM SpecProducts WHERE Name LIKE '%'+@p_name+'%' UNION ALL SELECT tab.ID, tab.Hierarchy, tab.Name --, p._Level+1 FROM SpecProducts tab INNER JOIN Temp_parents p ON p.Hierarchy.ToString() LIKE tab.Hierarchy.ToString()+'_/') ,Temp_descendants AS ( SELECT ID, Hierarchy, Name --, 0 _Level FROM SpecProducts WHERE Name LIKE '%'+@p_name+'%' UNION ALL SELECT tab.ID, tab.Hierarchy, tab.Name --, d._Level-1 FROM SpecProducts tab INNER JOIN Temp_descendants d ON tab.Hierarchy.ToString() LIKE d.Hierarchy.ToString()+'_/') SELECT * FROM Temp_parents UNION SELECT * FROM Temp_descendants
答案 2 :(得分:0)
也许是这样的:
select id, HierarchyID, Description from (
select b.id, b.HierarchyID, b.Description,
case
when (a.id = b.id) then 1
when (marker = 1 and num_len > 1 and LEN(replace(b.HierarchyID,'/','')) < num_len and numbers > replace(b.HierarchyID,'/','')) then 1
when (marker = 1 and num_len = 1 and LEN(replace(b.HierarchyID,'/','')) > num_len and numbers < replace(b.HierarchyID,'/','')) then 1
else 0 end as marker from (
select id, SUBSTRING(HierarchyID,2,1) as first_num, 1 as marker, replace(HierarchyID,'/','') as numbers, LEN(replace(HierarchyID,'/','')) as num_len
from my_tab where Description like '%bi%' or HierarchyID = '/') a right join my_tab b on first_num = SUBSTRING(b.HierarchyID,2,1)) c where marker = 1;
抱歉我的英语!
选择ID,您在HierarchyID中找到的第一个数字(“/ 2/1 /”为2),您找到的值的“标记”,您想要保留(标记= 1),完整您可以在HierarchyID(“/ 2/1 /”为21)中找到的数字,以及您在my_tab表(a)的HierarchyID中找到的完整数字的长度以及您选择的搜索词。
使用(1.)我们对my_tab表(b)进行右连接以获取所有其他值。 第一种情况:如果(a)中的id等于(b)的id,我们取标记1(因为这是我们用搜索项得到的值)。第二种情况:如果标记是1并且(a)的长度> 1(这意味着我们有一个像“/ 2/1 /”的值)和(b)的长度&lt; (a)的长度(表示“/ 2/2 /”有标记= 1,长度为2;“/ 2/1 /”具有相同的长度,但我们不想要他;我们想要“/ 2 / “)你可以在HierarchyID(a)中找到的完整数字大于你在HierarchyID(b)中找到的完整数字(这意味着我们将得到”/ 2 /“值)我们将标记设置为1。情况何时:类似于“第二种情况”。在这里,我们看一下标记= 1和长度为1(“/ 2 /”)的值,以标记我们想要的所有值,如“/ 2/1 /”和“/ 2/2 /”。 / p>
现在,您可以使用marker = 1获得所需的所有值。