Я получаю данные имени и адреса из общих данных вопроса/ответа, чтобы создать какую-то нормализованную базу данных отчетов.
Запрос, который у меня есть, использует group_concat и работает для отдельных наборов вопросов, но не для нескольких наборов.
Я попытался упростить то, что я делаю, используя только имя и фамилию и всего 3 записи, 2 для одного человека и 1 для другого. В действительности же существует более 300 000 записей.
Пример результатов с qs.Id = 1
.
QuestionSetId Forename Surname
-------------------------------------------------------
1 Bob Jones
Пример результатов с qs.Id IN (1, 2, 3)
.
QuestionSetId Forename Surname
-------------------------------------------------------
3 Bob,Bob,Frank Jones,Jones,Smith
Что я хотел бы видеть для qs.Id IN (1, 2, 3)
.
QuestionSetId Forename Surname
-------------------------------------------------------
1 Bob Jones
2 Bob Jones
3 Frank Smith
Итак, как я могу заставить второй пример возвращать отдельную строку для каждого набора информации об имени и адресе?
Я понимаю, что текущий способ хранения данных "сомнительный", но я не могу изменить способ хранения данных.
Я могу получить наборы отдельных ответов, но не знаю, как объединить остальные.
Моя упрощенная схема, которую я не могу изменить:
CREATE TABLE StaticQuestion (
Id INT NOT NULL,
StaticText VARCHAR(500) NOT NULL);
CREATE TABLE Question (
Id INT NOT NULL,
Text VARCHAR(500) NOT NULL);
CREATE TABLE StaticQuestionQuestionLink (
Id INT NOT NULL,
StaticQuestionId INT NOT NULL,
QuestionId INT NOT NULL,
DateEffective DATETIME NOT NULL);
CREATE TABLE Answer (
Id INT NOT NULL,
Text VARCHAR(500) NOT NULL);
CREATE TABLE QuestionSet (
Id INT NOT NULL,
DateEffective DATETIME NOT NULL);
CREATE TABLE QuestionAnswerLink (
Id INT NOT NULL,
QuestionSetId INT NOT NULL,
QuestionId INT NOT NULL,
AnswerId INT NOT NULL,
StaticQuestionId INT NOT NULL);
Некоторые примеры данных только для имени и фамилии.
INSERT INTO StaticQuestion (Id, StaticText)
VALUES (1, 'FirstName'),
(2, 'LastName');
INSERT INTO Question (Id, Text)
VALUES (1, 'What is your first name?'),
(2, 'What is your forename?'),
(3, 'What is your Surname?');
INSERT INTO StaticQuestionQuestionLink (Id, StaticQuestionId, QuestionId, DateEffective)
VALUES (1, 1, 1, '2001-01-01'),
(2, 1, 2, '2008-08-08'),
(3, 2, 3, '2001-01-01');
INSERT INTO Answer (Id, Text)
VALUES (1, 'Bob'),
(2, 'Jones'),
(3, 'Bob'),
(4, 'Jones'),
(5, 'Frank'),
(6, 'Smith');
INSERT INTO QuestionSet (Id, DateEffective)
VALUES (1, '2002-03-25'),
(2, '2009-05-05'),
(3, '2009-08-06');
INSERT INTO QuestionAnswerLink (Id, QuestionSetId, QuestionId, AnswerId, StaticQuestionId)
VALUES (1, 1, 1, 1, 1),
(2, 1, 3, 2, 2),
(3, 2, 2, 3, 1),
(4, 2, 3, 4, 2),
(5, 3, 2, 5, 1),
(6, 3, 3, 6, 2);
На всякий случай, если SQLFiddle не работает, вот 3 запроса из примеров, на которые я ссылался:
1: - рабочий запрос, но только на 1 наборе данных.
SELECT MAX(QuestionSetId) AS QuestionSetId,
GROUP_CONCAT(Forename) AS Forename,
GROUP_CONCAT(Surname) AS Surname
FROM (SELECT
x.QuestionSetId,
CASE x.StaticQuestionId WHEN 1 THEN Text END AS Forename,
CASE x.StaticQuestionId WHEN 2 THEN Text END AS Surname
FROM (SELECT (SELECT link.StaticQuestionId
FROM StaticQuestionQuestionLink link
WHERE link.Id = qa.QuestionId
AND link.DateEffective <= qs.DateEffective
AND link.StaticQuestionId IN (1, 2)
ORDER BY link.DateEffective DESC LIMIT 1) AS StaticQuestionId,
a.Text,
qa.QuestionSetId
FROM QuestionSet qs
INNER JOIN QuestionAnswerLink qa ON qs.Id = qa.QuestionSetId
INNER JOIN Answer a ON qa.AnswerId = a.Id
WHERE qs.Id IN (1)) x) y
2: - рабочий запрос, но нежелательные результаты для нескольких наборов данных.
SELECT MAX(QuestionSetId) AS QuestionSetId,
GROUP_CONCAT(Forename) AS Forename,
GROUP_CONCAT(Surname) AS Surname
FROM (SELECT
x.QuestionSetId,
CASE x.StaticQuestionId WHEN 1 THEN Text END AS Forename,
CASE x.StaticQuestionId WHEN 2 THEN Text END AS Surname
FROM (SELECT (SELECT link.StaticQuestionId
FROM StaticQuestionQuestionLink link
WHERE link.Id = qa.QuestionId
AND link.DateEffective <= qs.DateEffective
AND link.StaticQuestionId IN (1, 2)
ORDER BY link.DateEffective DESC LIMIT 1) AS StaticQuestionId,
a.Text,
qa.QuestionSetId
FROM QuestionSet qs
INNER JOIN QuestionAnswerLink qa ON qs.Id = qa.QuestionSetId
INNER JOIN Answer a ON qa.AnswerId = a.Id
WHERE qs.Id IN (1, 2, 3)) x) y
3: - рабочий запрос для нескольких наборов данных только в 1 поле (ответ).
SELECT
qs.Id AS QuestionSet,
a.Text AS Answer
FROM
QuestionSet qs
INNER JOIN QuestionAnswerLink qalink ON qs.Id = qalink.QuestionSetId
INNER JOIN StaticQuestionQuestionLink sqqlink ON qalink.QuestionId = sqqlink.QuestionId
INNER JOIN Answer a ON qalink.AnswerId = a.Id
WHERE
sqqlink.StaticQuestionId = 1 /* FirstName */
AND sqqlink.DateEffective =
(SELECT DateEffective
FROM StaticQuestionQuestionLink
WHERE StaticQuestionId = 1
AND DateEffective <= qs.DateEffective
ORDER BY DateEffective
DESC
LIMIT 1)