2013-12-08 5 views
2

У меня есть таблица пользователей, которая содержит столбец xml для хранения пользовательских полей для демографических данных, которые исходят из анкеты профиля.Запрос столбца XML против другого

Демографические пример записи для пользователя:

<demographics> 
     <question_1>answer_1</question_1> 
     <question_2>answer_2</question_2> 
     <question_3>answer_3</question_3> 
    </demographics> 

таблица назначений имеет еще один столбец XML для права пользователей, что опять-таки основана на анкете профиля.

<Eligibility> 
    <Expression> 
    <Question>question_1</Question> 
    <Answer>answer_1</Answer> 
    </Expression> 
    <Expression> 
    <Question>question_3</Question> 
    <Answer>answer_3</Answer> 
    </Expression> 
</Eligibility> 

Мне нужно найти все задания, которые соответствуют демографии пользователя на основе XML критериев, определенных в таблице. Оператор между критериями приемлемости должен быть «И». Ниже приведен запрос, который я написал

SELECT * 
    FROM Assignments AS a 
    WHERE Eligibility.exist('/Eligibility/Expression[Question= 1 and Answer=1]') = 1 
    AND Eligibility.exist('/Eligibility/Expression[Question= 2 and Answer=2]') = 1 

Предположим, что у нас есть два назначения A1 и A2. A1 имеет критерии как Question1 = Answer1, а A2 имеет критерии Question2 = Answer2. Оба назначения удовлетворяют требованиям для пользователя. Однако указанный выше запрос не возвращает ни одно из двух назначений из-за «И» между критериями приемлемости.

Любая помощь будет оценена по достоинству.

ответ

4

Это фактически запрос relational division, который использует данные XML.

Комментарии в коде описывают, что происходит в каждой части запроса.

-- A users demographics 
declare @UserDem xml = ' 
<demographics> 
    <question_1>answer_1</question_1> 
    <question_2>answer_2</question_2> 
    <question_3>answer_3</question_3> 
</demographics>'; 

-- Get ID for the assignment 
select A.ID 
from Assignments as A 
    -- Calculate the number of Expression there are in each assignment 
    cross apply (select A.Eligibility.value('count(/Eligibility/Expression)', 'int')) as C(ECount) 
    -- Shred on Expression 
    cross apply A.Eligibility.nodes('/Eligibility/Expression') as E(X) 
    -- Join to demographics on question and answer 
    inner join @UserDem.nodes('demographics/*') as D(X) 
    on D.X.value('local-name(.)[1]', 'nvarchar(100)') = E.X.value('(Question/text())[1]', 'nvarchar(100)') and 
     D.X.value('text()[1]', 'nvarchar(100)') = E.X.value('(Answer/text())[1]', 'nvarchar(100)') 
-- Group on ID and get the Assignments that are fully covered by the demographic 
group by A.ID, C.ECount 
having count(*) = C.ECount; 

SQL Fiddle

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