2015-05-05 3 views
0

У меня есть стол A, с колоннами Id и ParentId. Учитывая Id, я хочу вернуть все ParentId.Использование SQL Server, как вернуть список из цикла While, и должен ли я использовать цикл While?

Значение, дается Id, я хочу, чтобы вернуть все записи ParentId, а затем я хочу, чтобы проверить, если записанный ParentId вводится в таблицу как Id, если это так я хочу найти это ParentId и т.д. ...

Например, если у меня есть простой пример таблицы, как:

Id | ParentID 
---+--------- 
1 0  
2 1 
3 2 
4 3 
5 4 
6 5 
7 6 

Мой запрос на печать всех родителей из Id=7 выглядит следующим образом:

DECLARE @ParentId INT; 

SET @ParentId = 7; 

WHILE(@ParentId > 0) 
BEGIN 
    SELECT @ParentId = ParentId 
    FROM A 
    WHERE Id = @ParentID 

    PRINT @ParentId 
END 

Этот запрос распечатывает все ParentId. Но есть ли способ вернуть идентификаторы? В этом случае, если бы я вызывал этот запрос с PHP, я бы хотел получить список ParentIds, но мой запрос на самом деле ничего не возвращает.

Кроме того, мне интересно, является ли цикл while правильным решением. Будет ли рекурсивный запрос быстрее? Если да, то какие рекомендации о том, как преобразовать это в рекурсивный запрос?

* Редактировать

Мне нужно получить доступ к списку ParentIds из PHP. Теперь я пытаюсь создать список идентификаторов с разделителями-запятыми для возврата из запроса, который я могу позже проанализировать в PHP. Тем не менее, ниже запрос дает мне сообщение об ошибке:

A RETURN statement with a return value cannot be used in this context.

DECLARE @ParentId INT, @ParentList varchar(max); 

    SET @ParentId = 7; 

    WHILE(@ParentId > 0) 
    BEGIN 
     SELECT @ParentId = ParentId 
     FROM A 
     WHERE Id = @ParentID 

     SET @ParentList = @ParentList | CAST(@ParentId as varchar(20)) | ','; 
    END 
    RETURN @ParentList; 

Что я должен сделать, чтобы вернуть список? Кроме того, как я могу получить возвращаемое значение при выполнении этого выражения в PHP?

+0

Хотя циклы и рекурсивные вызовы метода эквивалентны. – Jonast92

+0

Являются ли они эквивалентными с точки зрения производительности? – ab11

+0

Цикл while всегда будет страдать от точки зрения производительности. Часто рекурсивный цит не будет страдать от одного и того же штрафа за производительность. Из вашего описания я бы подумал, что рекурсивный cte - это именно то, что вам нужно. –

ответ

1

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

declare @parents table 
(
    LVL int primary key identity(1,1), -- [optional] level in hierarchy 
    ParentID int 
) 
DECLARE @ParentId INT; 
SET @ParentId = 7; 
WHILE(@ParentId > 0) 
BEGIN 
    SELECT @ParentId=ParentId 
    FROM A 
    WHERE [email protected] 

    -- PRINT @ParentId 
    if (@ParentId > 0) 
    insert into @parents (ParentID) values (@ParentId) 
END 

select * from @parents 

если вы хотите рекурсивный запрос, попробуйте искать recursive cte in sql-server

можно создать @parentList varchar(max) переменные и возврат результат в виде строки '6,5,4,3,2,1' и разделить его на стороне клиента, но этот формат не является полезным в дб

DECLARE @ParentId INT, @ParentList varchar(max) = ''; 
-- @ParentList should be initialized with non-NULL value 

SET @ParentId = 7; 

WHILE(@ParentId > 0) 
BEGIN 
    SELECT @ParentId = ParentId 
    FROM A 
    WHERE Id = @ParentID 

    SET @ParentList = @ParentList + CAST(@ParentId as varchar(20)) + ','; 
END 
select @ParentList; 
+0

Нет концепции построения списка в цикле, а затем возврата списка после завершения цикла? – ab11

+0

@ ab11, это реляционная база данных, поэтому она работает со столами. можно создать переменную '@parentList varchar (max)' и вернуть результат в виде строки ''6,5,4,3,2,1'' и разделить ее на стороне клиента, но этот формат не является полезным в дБ. почему бы просто не вернуть набор значений? – ASh

+0

Я вызываю этот запрос из php. Мне нужно, чтобы он вернул список идентификаторов, поэтому ваше предложение похоже на то, что я хотел бы сделать. Однако у меня проблемы с работой. Можете ли вы посмотреть на редактирование, которое я сделал на мой вопрос? – ab11

1
SELECT child.ParentID 
FROM A child 
      INNER JOIN A parent 
      ON child.Id = parent.ParentID 

Результат

0 
1 
2 
3 
4 
5 
6 
7 

Чтобы вернуть список строки

DECLARE @List NVARCHAR(MAX) 

SELECT @List = COALESCE(@List + ',', '') + child.ParentID 
FROM A child 
      INNER JOIN A parent 
      ON child.Id = parent.ParentID 

SELECT @List 

Результат
0,1,2,3,4,5,6,7

+3

Не могли бы вы объяснить, почему это дает решение, которое ищет @ ab11? –

+0

это не решение. query равен 'select ParentID от A' – ASh

+0

Я добавляю функцию COALESCE для возврата результата в виде списка id –

0

Просто предложение, если вы можете создать и поддерживать две таблицы (один для родителей, один для детей) лет u может воспользоваться соотношением между двумя наборами данных. Следовательно, R в СУБД.Если бы у вас было 3 родителей с 3 детьми каждый из них, это могло бы выглядеть так:

tblParents.ParentID 
1 --Children are 1,2,3 
2 --Children are 4,5,6 
3 --Children are 7,8,9 

tblChildren.ChildID, tblChildren.ParentID 
1,1 --Parent 1's children 
2,1 
3,1 
4,2 --Parent 2's children 
5,2 
6,2 
7,3 --Parent 3's children 
8,3 
9,3 

Итак, вернемся к исходному вопросу. В этом случае, если вы знаете ChildID, вы можете объединить таблицы Child и Parent вместе с ParentID. Затем вы можете получить информацию о родителях, зная только ChildID.

Другие комментарии отвечают на ваш вопрос, но не решают проблему моделирования данных!

Надеюсь, что это поможет!

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