一般的な質問/回答データから名前と住所のデータを取得して、ある種の正規化されたレポート データベースを作成しています。
私が持っているクエリは group_concat を使用しており、個々の質問セットでは機能しますが、複数のセットでは機能しません。
名字と姓だけを使用し、3 つのレコード (1 人に 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
では、2 番目の例で、名前と住所の情報セットごとに個別の行を返すようにするにはどうすればよいでしょうか?
現在のデータの保存方法は「疑わしい」と認識していますが、データの保存方法を変更することはできません。
個々の回答のセットを取得できますが、他の回答を組み合わせる方法がわかりません。
変更できない単純化されたスキーマ:
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)