4

我从通用问题/答案数据中获取姓名和地址数据,以创建某种标准化报告数据库。

我得到的查询使用 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

那么如何使第二个示例为每组名称和地址信息返回单独的行?

我意识到当前的数据存储方式是“有问题的”,但我无法更改数据的存储方式。

我可以得到一组单独的答案,但不确定如何组合其他答案。

我无法更改的简化架构:

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: - 工作查询,但仅针对一组数据。

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)
4

2 回答 2

3

@PeteGo,试试这个

SELECT
    qs.Id AS QuestionSet,
    GROUP_CONCAT(a.Text SEPARATOR ', ')  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 in (1,2,3) /* FirstName */
GROUP BY qs.Id;

或者

SELECT
    qs.Id AS QuestionSet,
    group_CONCAT(b.Text ORDER BY b.Id )   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
INNER JOIN Answer b ON qalink.AnswerId = b.Id
WHERE
        sqqlink.StaticQuestionId in (1,2,3)  
   group by qs.Id  ;

或者

select qs.Id, group_concat(a.Text order by a.Id) from QuestionAnswerLink qalink
left join QuestionSet qs on qalink.QuestionSetId=qs.Id
left join Answer a on qalink.AnswerId = a.Id


 left join QuestionSet qs1 on qalink.QuestionSetId=qs1.Id
left join Answer b on qalink.AnswerId = b.Id


group by qs.Id ;
于 2012-12-06T22:44:42.147 回答
2

从@PixelMaker 和@PeteGO 窃取,我会把这个扔进去

SELECT qs.Id AS QuestionSetId,
       GROUP_CONCAT(a.Text order by a.id) AS Answer
FROM QuestionSet qs
JOIN QuestionAnswerLink qa ON qs.Id = qa.QuestionSetId
JOIN StaticQuestionQuestionLink link ON qa.QuestionId = link.QuestionId
JOIN Answer a ON qa.AnswerId = a.Id
WHERE link.Id = qa.QuestionId
      AND link.DateEffective <= qs.DateEffective
      AND link.StaticQuestionId IN (1, 2)
      and qs.id in (1,2,3)
GROUP BY qs.Id

SQL小提琴

最后是这个SQL Fiddle

SELECT qs.Id AS QuestionSetId,
       GROUP_CONCAT(case link.staticquestionid when 1 then a.Text end) AS forename,
       GROUP_CONCAT(case link.staticquestionid when 2 then a.Text end) AS surname
FROM QuestionSet qs
JOIN QuestionAnswerLink qa ON qs.Id = qa.QuestionSetId
JOIN StaticQuestionQuestionLink link ON qa.QuestionId = link.QuestionId
JOIN Answer a ON qa.AnswerId = a.Id
WHERE link.Id = qa.QuestionId
      AND link.DateEffective <= qs.DateEffective
      AND link.StaticQuestionId IN (1, 2)
      and qs.id in (1,2,3)
GROUP BY qs.Id

这给出了预期的结果。

于 2012-12-06T23:14:53.027 回答