SQL сравнивать таблицы и возвращать битовый массив или CSV - PullRequest
1 голос
/ 29 ноября 2010

Это сложный вопрос! У меня есть две таблицы tblPeopleAnswers и tblAnswers

tblPeopleAnswers

PersonID QuestionID AnswerID
15       5          1
15       5          3
17       5          1
17       5          2

tblAnswers

QuestionID AnswerID
5          1
5          2
5          3

Я хотел бы пройтись по каждому PersonID и вернуть битовый массив или CSV своих ответов по сравнению с доступными ответами. Так, для приведенного выше примера PersonID - массив 15 битов - 101, PersonID - массив 17 битов - 110.

выводимый

PersonID QuestionID BitAnswer
15       5          101
17       5          110

Мне нужно, чтобы все это было сделано в SQL Server 2008.

У меня есть по меньшей мере 1000 человек, 1000 вопросов и 5 ответов на вопрос, поэтому мне тоже нужна какая-то скорость.

1 Ответ

2 голосов
/ 29 ноября 2010

Возможно, термин, который вы ищете для описания того, что вы хотите, это "битовая маска".

Это работает путем составления списка всех возможных комбинаций людей и ответов, объединения его с фактическими ответами и последующего использования рекурсивного CTE для объединения результатов в одну строку:

DECLARE @tblPeopleAnswers TABLE
(PersonID INT 
,QuestionID INT
,AnswerID INT
)

INSERT @tblPeopleAnswers
VALUES (15,5,1),
(15, 5, 3),
(17, 5, 1),
(17, 5, 2)

DECLARE @tblAnswers TABLE
(QuestionID INT
,AnswerID INT
)

INSERT @tblAnswers
VALUES
(5,1),
(5,2),
(5,3)

;WITH ansCTE
AS
(
    SELECT answers.PersonID,
            answers.QuestionId,
            answers.AnswerId,
            CASE WHEN tpa.PersonID IS NULL 
                THEN '0'
                ELSE '1'
            END AS RESULT,
            ROW_NUMBER() OVER (PARTITION BY answers.PersonId, answers.QuestionId
                                ORDER BY    answers.AnswerId DESC
                                ) AS rn

    FROM (SELECT * FROM 
            (SELECT DISTINCT PersonID FROM @tblPeopleAnswers) AS z -- you may have @tblPeople you could use here??
            CROSS JOIN @tblAnswers
            ) AS answers
    LEFT JOIN @tblPeopleAnswers AS tpa
    ON tpa.QuestionID = answers.QuestionID
    AND tpa.AnswerId = answers.AnswerId
    AND tpa.PersonID = answers.PersonID
)
,recCTE
AS
(
    SELECT PersonId,
            QuestionId,
            AnswerId,
            CAST (RESULT AS VARCHAR(MAX)) AS BitAnswer,
            rn
    FROM ansCTE WHERE AnswerID = 1
    UNION ALL
    SELECT r.PersonId,
           r.QuestionId,
           a.AnswerID,
           r.BitAnswer + CAST(a.Result AS CHAR(1)),
           a.rn
    FROM recCTE AS r
    JOIN ansCTE AS a
    ON   a.PersonID = r.PersonID
    AND  a.QuestionID = r.QuestionID
    AND  a.AnswerID = r.AnswerID + 1
)
SELECT PersonId, 
       QuestionId,
       BitAnswer
FROM recCTE
WHERE rn = 1
ORDER BY PersonID, QuestionID
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...