我在Microsoft SQL环境中有以下场景:
#include<stdio.h>
int BinarySearch(int l, int h, int *a, int x );
int main()
{
int a[10], n, i, x, r=1, q=0;
int *p= &a[0];
printf("Enter the number of elements :\n");
scanf("%d", &n);
printf("Enter the elements :\n");
for(i=0; i<n; i++)
scanf("%d", &a[i]);
printf("Enter the element to be searched :\n");
scanf("%d", &x);
r=BinarySearch(q, n-1, p, x);
if(r==-1)
printf("The element %d is not present in the array\n", x);
else
printf("The element %d is in position %d", x, r);
return 0;
}
int BinarySearch(int l, int h, int *a, int x)
{
while(l<=h)
{
int m;
m=(l+(h-1))/2;
if (a[m]==x)
return m;
if(a[m]<x)
l=m+1;
else
h=m-1;
}
return -1;
}
我试图根据孩子的身份得到父母。如果查询的id是最后一个父项,那么它应该只返回最后一项。
示例:
CREATE TABLE grps
(
[id] varchar(50),
[parentid] varchar(50),
[value] varchar(50)
);
INSERT INTO grps
([id], [parentid], [value])
VALUES
('-5001', '0', null),
('-5002', '-5001', null),
('-5003', '-5002', '50'),
('-5004', '-5003', null),
('-5005', '0', null),
('-5006', '0', null),
('-5007', '0', null),
('-5008', '-5006', null);
,则应返回id = '-5004'
('-5004', '-5003', null),
('-5003', '-5002', '50'),
('-5002', '-5001', null),
('-5001', '0', null)
,则应返回id = '-5007'
如果它可以列出首先查询的id并且其余部分以有序的方式列出&#34;树&#34;那将是非常棒的。
我已经尝试了几种不同的CTE方法,但遗憾的是没有运气。所以我在这里寻找一些帮助或想法。
提前致谢。
答案 0 :(得分:3)
你和CTE一起走在了正确的轨道上。它可以通过使用递归CTE来完成!以下是递归CTE的样子:
DECLARE @ID varchar(50) = '5004';
WITH CTE AS
(
--This is called once to get the minimum and maximum values
SELECT id, parentid, value
FROM grps
WHERE id= @ID
UNION ALL
--This is called multiple times until the condition is met
SELECT g.id, g.parentid, g.value
FROM CTE c, grps g
WHERE g.id= c.parentid
--If you don't like commas between tables then you can replace the 2nd select
--statement with this:
--SELECT g.id, g.parentid, g.value
--FROM CTE c
--INNER JOIN grps g ON g.id= c.parentid
--This can also be written with CROSS JOINS!
--Even though it looks more like another way of writing INNER JOINs.
--SELECT g.id, g.parentid, g.value
--FROM CTE c
--CROSS JOIN grps g
--WHERE g.id = c.parentid
)
SELECT * FROM CTE
请注意,除非您将option (maxrecursion 0)
添加到最后一个select语句的末尾,否则最大递归为100。 0表示无限,但您也可以将其设置为您想要的任何值。
享受!
答案 1 :(得分:2)
我正在尽力为这个世界的某种爱人提供一些爱。首先,设置:
CREATE TABLE grps
(
[id] varchar(50),
[parentid] varchar(50),
[value] varchar(50),
h HIERARCHYID NULL
);
SELECT * FROM grps
INSERT INTO grps
([id], [parentid], [value])
VALUES
('-5001', '0', null),
('-5002', '-5001', null),
('-5003', '-5002', '50'),
('-5004', '-5003', null),
('-5005', '0', null),
('-5006', '0', null),
('-5007', '0', null),
('-5008', '-5006', null);
WITH cte AS (
SELECT id ,
parentid ,
value ,
CAST('/' + id + '/' AS nvarchar(max)) AS h
FROM grps
WHERE parentid = 0
UNION ALL
SELECT child.id ,
child.parentid ,
child.value ,
CAST(parent.h + child.id + '/' AS NVARCHAR(MAX)) AS h
FROM cte AS [parent]
JOIN grps AS [child]
ON child.parentid = parent.id
)
UPDATE g
SET h = c.h
FROM grps AS g
JOIN cte AS c
ON c.id = g.id
我在这里所做的就是在表定义中添加一个hierarchyid列并计算它的值。要确定回答原始问题,现在它看起来像这样:
SELECT g.id ,
g.parentid ,
g.value ,
g.h.ToString()
FROM dbo.grps AS g
JOIN grps AS c
ON c.h.IsDescendantOf(g.h) = 1
WHERE c.id = '-5004'
为了提高性能,您应该独立地索引id和h列(即,在单独的索引中)。
另外,还有几个笔记
当数据看起来是数字时,将id列设为varchar充其量是多余的,但更重要的是它效率低下。如果是我,我会使用int。但也许你的实际数据比较混乱(即你有像'A1234'这样的ids)。
我还会使用NULL
而不是0来表示parentid代表顶级(即那些没有父级的成员)。但这更多是个人选择,而不是具有任何实际性能影响的选择。