2015-01-17 4 views
0

У меня есть таблица города каквыбрать, если матч поля или, если матч ребенок запись поля

(Id, Name, ParentId) 

где ParentId является Id из города (самостоятельно, связанные таблицы)

Я хочу, чтобы получить города Wheres ParentID равна нулю (корень) если имя совпадает или имя ребенка запись соответствует я написал

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 

Что я могу сделать, чтобы сделать это быстрее и лучше?
Edit:

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:
первые выберите возвращает города с соответствующими именами
второй выберите возвратов города с соответствующими детьми
затем объединить два результата.

+0

Добавить некоторые данные испытаний и ожидаемые результаты. –

+0

@GiorgiNakeuri Сделано! – Star

+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)) 
+0

Спасибо, что он работает так, как ожидалось, но не могли бы вы немного объяснить?Я не уверен, что понимаю, что происходит. @Giorgi Nakeuri – Star

+0

извините была ошибка. Я обновил ответ. подтвердите пожалуйста еще раз. Я обновлю объяснение в течение 5 минут –

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) 
+0

Обновлено. Отметьте @Star –

+0

Спасибо за ответ, но ваш пример возвращает только первую строку (в моих данных примера) – Star

+0

** PARENTID IS Null ** с подходящим случаем ** CD ** имеют только один родитель. И у этого родителя нет ребенка с ** CD ** в качестве подходящего случая @Star –

Смежные вопросы