选择字段匹配或子记录字段是否匹配

时间:2015-01-17 09:39:48

标签: sql sql-server

我有一个表格城市

(Id, Name, ParentId)

其中ParentId是城市的Id(自相关表)

我想得到parentId为null(根)的城市 如果名称匹配或子记录名称匹配我写了这个

declare @cities table (Id, Name, ParentId)

insert into @cities (Id , Name) 
select Id , Name from Cities
Where CHARINDEX(N'CD', Name) > 0 and ParentId is null 

insert into @cities (Id , Name) 
select Id , Name from Cities
Where Id in 
   (select distinct ParentId from Cities 
    where CHARINDEX(N'CD', Name) > 0 ParentId is not null) 
and ParentId is null 

select distinct * from @cities 

我能做些什么来让它变得更快更好? 编辑:

Id  | Name  | ParentId 
----------------------
1   | ABCD  | NULL
----------------------
2   | EFZX  | NULL
----------------------
3   | GHIJ  | NULL
----------------------
4   | MNOP  | 1
----------------------
5   | CDKL  | 2
----------------------
6   | QRST  | 3
----------------------

这应该返回:

Id  | Name  | ParentId 
----------------------
1   | ABCD  | NULL
----------------------
2   | EFZX  | NULL
----------------------

EDIT2:
第一个选择返回匹配名称为的城市 第二个选择返回具有匹配子项的城市 然后合并两个结果。

2 个答案:

答案 0 :(得分:1)

我可以用一个选择建议解决方案。 我认为你想要父母和直系后代的结果。因此,您应该选择名称匹配的所有行' CD'

SELECT * FROM @cities
WHERE CHARINDEX(N'CD', Name) > 0

这会给你

1   ABCD    NULL
5   CDKL    2
6   CDKP    2

您希望仅选择父母,这就是为什么您需要在父级上进行左连接以获取父级为2的行

SELECT *  FROM @cities c1
LEFT JOIN @cities c2 ON c1.ParentId = c2.ID
WHERE CHARINDEX(N'CD', c1.Name) > 0 

返回

1   ABCD    NULL    NULL    NULL    NULL
5   CDKL    2       2       EFZX    NULL
6   CDKP    2       2       EFZX    NULL

然后你在and (c1.ParentId is NULL OR (c1.ParentId IS NOT NULL AND c2.ParentId IS NULL))的第二位申请,只接纳父母和直系亲属。

 declare @cities table (Id int, Name NVARCHAR(MAX), ParentId INT null)

INSERT INTO @cities (Id, Name, ParentId) VALUES (1, 'ABCD', NULL)
INSERT INTO @cities (Id, Name, ParentId) VALUES (2, 'EFZX', NULL)
INSERT INTO @cities (Id, Name, ParentId) VALUES (3, 'GHIJ', NULL)
INSERT INTO @cities (Id, Name, ParentId) VALUES (4, 'MNOP', 1)
INSERT INTO @cities (Id, Name, ParentId) VALUES (5, 'CDKL', 2)
INSERT INTO @cities (Id, Name, ParentId) VALUES (6, 'CDKP', 2)




SELECT DISTINCT ISNULL(c2.Id, c1.Id), ISNULL(c2.Name, c1.Name)  FROM @cities c1
LEFT JOIN @cities c2 ON c1.ParentId = c2.ID
WHERE CHARINDEX(N'CD', c1.Name) > 0 and (c1.ParentId is NULL  OR (c1.ParentId IS NOT NULL AND c2.ParentId IS NULL))

答案 1 :(得分:0)

示例代码

CREATE table #cities  (Id INT, Name VARCHAR(30), ParentId INT)


insert into #cities (Id, Name, ParentId) VALUES(1 , 'ABCD',NULL) 
insert into #cities (Id, Name, ParentId) VALUES(2 , 'EFZX',NULL) 
insert into #cities (Id, Name, ParentId) VALUES(3 , 'GHIJ',NULL) 
insert into #cities (Id, Name, ParentId) VALUES(4 , 'MNOP',1) 
insert into #cities (Id, Name, ParentId) VALUES(5 , 'CDKL',2) 
insert into #cities (Id, Name, ParentId) VALUES(6 , 'QRST',3) 

<强> QUERY

;WITH CTE AS
(
    -- Select condition for parent
    SELECT Id, Name, ParentId,0 AS [LEVEL]
    FROM #cities --WHERE ParentId IS NULL --AND ID=1
    WHERE CHARINDEX(N'CD', Name) > 0 and ParentId is null 
    UNION ALL 
    SELECT C1.*,C2.[LEVEL]+1 
    FROM #cities C1
    JOIN CTE C2 ON C1.ParentId=C2.Id
)
-- Since you get only parent and children, you can filter children here
SELECT * 
FROM CTE
WHERE CHARINDEX(N'CD', Name) > 0 
OPTION(MAXRECURSION 0)