Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/81.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 使用递归CTE查找父级和子级_Sql_Sql Server 2005_Tsql_Common Table Expression - Fatal编程技术网

Sql 使用递归CTE查找父级和子级

Sql 使用递归CTE查找父级和子级,sql,sql-server-2005,tsql,common-table-expression,Sql,Sql Server 2005,Tsql,Common Table Expression,我有一个小要求 DECLARE @t TABLE (Data VARCHAR(50)) INSERT INTO @t SELECT 'A,B,C' UNION ALL SELECT 'I,J,K' UNION ALL SELECT 'A,D' SELECT DISTINCT b.Item AS Child, CASE WHEN CHARINDEX(b.Item,a.Data)=1 THEN null ELSE SUBSTRING(a.data, 1,CHARINDEX(',',a.dat

我有一个小要求

DECLARE @t TABLE (Data VARCHAR(50))
INSERT INTO @t SELECT 'A,B,C' UNION ALL SELECT 'I,J,K' UNION ALL SELECT 'A,D'

SELECT DISTINCT b.Item AS Child,
CASE WHEN 
CHARINDEX(b.Item,a.Data)=1 
THEN null 
ELSE SUBSTRING(a.data, 1,CHARINDEX(',',a.data)-1) END AS Parent  FROM @t a CROSS APPLY dbo.split(a.Data,',') b
我有一些数据如下

Data
-----
A,B,C
I,J,K
A,D
DDL如下所示

我要做的就是输出

Parent  Child
------- -------
Null    A
Null    I
A       B
A       C
I       J
J       K
A       D
到目前为止,我的方法仍在进行中,但不起作用

;With cte as ( 
  SSELECT Parent = null, Child = substring(data, 1, CHARINDEX(',',data)-1) 
    FROM @t
  Union all
  SELECT t.child, substring(t.data, CHARINDEX(',',t.data)+1, LEN(t.data)) 
    FROM @t t
    JOIN cte c ON c.child <> t.child )
Select * from cte
结果:

Parent   Child
------   -----
NULL     A
NULL     I
A        B
A        D
B        C
I        J
J        K
parent   child
-------- -----
NULL    A
NULL    I
A       B
A       D
B       C
I       J
J       K

您可以使用下面的select查询来查询需求

DECLARE @t TABLE (Data VARCHAR(50))
INSERT INTO @t SELECT 'A,B,C' UNION ALL SELECT 'I,J,K' UNION ALL SELECT 'A,D'

SELECT DISTINCT b.Item AS Child,
CASE WHEN 
CHARINDEX(b.Item,a.Data)=1 
THEN null 
ELSE SUBSTRING(a.data, 1,CHARINDEX(',',a.data)-1) END AS Parent  FROM @t a CROSS APPLY dbo.split(a.Data,',') b
为此,您需要有一个用户定义的Split函数,该函数返回表变量

CREATE FUNCTION [dbo].[Split]  
(  
 @ItemList VARCHAR(4000),  
 @delimiter VARCHAR(10)  
)  
RETURNS @IDTable TABLE (ID INT IDENTITY(1,1),Item VARCHAR(500))  
AS  
BEGIN  
-- This function is used to split up multi-value parameters  
 DECLARE @tempItemList NVARCHAR(4000)  
 SET @tempItemList = @ItemList  

 DECLARE @i INT  
 DECLARE @Item NVARCHAR(4000)  

 SET @tempItemList = REPLACE (@tempItemList, ' ' + @delimiter, @delimiter)  
 SET @tempItemList = REPLACE (@tempItemList, @delimiter + ' ', @delimiter)  
 SET @i = CHARINDEX(@delimiter, @tempItemList)   

 WHILE (LEN(@tempItemList) > 0)  
 BEGIN  
  IF @i = 0  
   SET @Item = @tempItemList  
  ELSE  
   SET @Item = LEFT(@tempItemList, @i -1)  

  INSERT INTO @IDTable(Item) VALUES(@Item)  

  IF @i = 0  
   SET @tempItemList = ''  
  ELSE  
   SET @tempItemList = RIGHT(@tempItemList, LEN(@tempItemList) - (@i + LEN(@delimiter)-1))  

  SET @i = CHARINDEX(@delimiter, @tempItemList)  
 END  
 RETURN  
END
如果可能的话,我宁愿建议更改所需的表结构,同时考虑性能


希望这是有用的。

只想检查一下,这是考虑性能的最佳方式。我已经检查过了,交叉应用和分割功能似乎是一个更好的性能选择。@suryakiran-我还没有对此进行任何性能测试。我不认为像这样拆分字符串是应该经常做的事情。也许只有当您需要通过规范化数据库结构来修复一个糟糕的数据库设计时。我建议在数据库设计中,随着表的增长,这不会产生乐观的输出。我认为我的版本在这里表现最好
DECLARE @t TABLE (Data VARCHAR(50)) 
INSERT INTO @t SELECT 'A,B,C' UNION ALL SELECT 'I,J,K' UNION ALL SELECT 'A,D' 

;WITH cte as (  
SELECT 
CAST(null AS VARCHAR(50)) Parent, 
Child = Left(data, CHARINDEX(',',data)-1), 
CAST(Stuff(data, 1, CHARINDEX(',',data), '') + ',' as VARCHAR(50)) Leftover 
FROM @t 
UNION ALL 
SELECT cte.Child, 
Left(cte.leftover, CHARINDEX(',',cte.leftover)-1), 
CAST(Stuff(cte.leftover, 1, CHARINDEX(',',cte.leftover ), '') as VARCHAR(50))
FROM cte
WHERE cte.leftover <> '')
SELECT DISTINCT parent, child FROM cte 
parent   child
-------- -----
NULL    A
NULL    I
A       B
A       D
B       C
I       J
J       K