2014-01-21 3 views
0

Моей проблемой может быть структура таблиц, с которыми я работаю, и я открыт для любых предложений. У меня есть следующие четыре таблицы, которые настроены, чтобы позволить компании иметь набор Вопросов, и у каждого Вопроса есть несколько ответов. Поток вопросов определяется выбранным выбранным answerID. Поэтому в зависимости от того, как человек отвечает на вопрос, он может быть направлен на другой вопрос, основанный на каждом ответе.Рекурсивный CTE для получения первого элемента

Моя текущая проблема заключается в том, что мне нужно иметь возможность получить первый вопрос в иерархии. Я попытался добиться этого с помощью рекурсивного CTE, но не верю, что правильно настроил его (или даже возможно из-за структуры таблицы), поскольку получаю максимальную ошибку рекурсии и подавляю максимум с опцией (maxrecursion 0) doesn Помогите, поскольку это, кажется, не завершается. Я предполагаю, что это происходит из-за того, что часть CTE, где он соединяется с собой, возвращает несколько строк. Пожалуйста, см. Ниже, что я имею в настоящее время.

create table Company 
(
    CompanyID int not null, 
    constraint pk_Company primary key (CompanyID) 
) 

create table Question 
(
    QuestionID int not null, 
    QuestionText varchar(250) not null, 
    constraint pk_Question primary key (QuestionID) 
) 

create table Answer 
(
    AnswerID int not null, 
    AnswerText varchar(250) not null, 
    constraint pk_Answer primary key (AnswerID) 
) 

create table CompanyQuestion 
(
    CompanyQuestionID int not null, 
    CompanyID int not null, 
    QuestionID int not null, 
    constraint pk_CompanyQuestion primary key (CompanyQuestionID), 
    constraint fk_CompanyQuestion_Company foreign key (CompanyID) references Company (CompanyID), 
    constraint fk_CompanyQuestion_Question foreign key (QuestionID) references Question (QuestionID) 
) 

create table CompanyAnswer 
(
    CompanyAnswerID int not null, 
    CompanyQuestionID int not null, 
    AnswerID int not null, 
    NextQuestionID int null, 
    constraint pk_CompanyAnswer primary key (CompanyAnswerID), 
    constraint fk_CompanyAnswer_CompanyQuestion foreign key (CompanyQuestionID) references CompanyQuestion (CompanyQuestionID), 
    constraint fk_CompanyAnswer_Answer foreign key (AnswerID) references Answer (AnswerID), 
    constraint fk_CompanyAnswer_NextQuestion foreing key (NextQuestionID) references CompanyQuestion (CompanyQuestionID) 
) 

with cte (CompanyQuestionID, NextQuestionID, Tier) 
as 
(
    select a.CompanyQuestionID, 
      a.NextQuestionID, 
      0 as 'Tier' 
    from CompanyAnswer a 
    where a.NextQuestionID is null 

    union all 

    select a.CompanyQuestionID, 
      a.NextQuestionID, 
      "Tier" + 1 
    from CompanyAnswer a 
    join cte 
     on a.NextQuestionID = cte.CompanyQuestionID 
    where a.NextQuestionID is not null 
) 

select CompanyQuestionID, 
     NextQuestionID, 
     Tier 
from cte 
+0

Просто чтобы проверить, измените его на 'где a.NextQuestionID не равно null, а [Tier] <= 10' Это все еще вызывает ошибку maxrecursion? – Anon

+0

Он работает, когда я это делаю, но я не верю, что дам мне ответ, который я ищу, не так ли? Разве я не буду искать самый высокий уровень, чтобы получить самый первый вопрос? –

+3

Учитывая, что он работает, когда вы его отключили, вы уверены, что в ваших данных нет циклов? i. Q1-> Q2-> Q3-> Q1. Если есть циклы, то у вас нет «самого высокого уровня» – Anon

ответ

0

В вашей логике ничего не происходит. Просто убедитесь, что ваши данные не имеют циклов. Если вам нужно их обнаружить, прочитайте алгоритм Тарьяна или алгоритм Дейкстры. http://hansolav.net/sql/graphs.html - хорошая отправная точка для работы с графиками в SQL.

+0

Спасибо за ссылку. Я буду читать об этом сегодня вечером. –

0

Я бы порекомендовал вам изменить ваш рекурсию пойти DOWN вместо UP просто изменить CompanyAnswer таблицу включить PreviousQuestionID вместо NextQuestionID

create table CompanyAnswer 
(
CompanyAnswerID int not null, 
CompanyQuestionID int not null, 
AnswerID int not null, 
PreviousQuestionID int null, 
) 

Это поможет вам всегда найти Главные вопросы родителей по

Select * from CompanyAnswer Where PreviousQuestionID is null 

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

+0

Спасибо за ваше предложение; Я не думаю, что смогу полностью удалить NextQuestionID, так как мне нужно знать, что следующий вопрос основан на выбранном ответе. В последнее время у меня был столбец PreviousQuestionID в дизайне, но я чувствовал, что его будет сложно поддерживать, если я обновляю экземпляр NextQuestionID CompanyAnswer, поскольку тогда мне придется запрашивать/обновлять другое значение CompanyAnswers PreviousQuestionID, чтобы полностью отразить это изменение. –

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