ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

MySQL查询GROUP_CONCAT多行

2019-06-20 18:02:38  阅读:246  来源: 互联网

标签:mysql aggregate group-concat


我从通用问题/答案数据中获取名称和地址数据,以创建某种规范化的报告数据库.

我得到的查询使用group_concat,适用于各个问题集,但不适用于多个集合.

我试图通过仅使用forename和surname以及仅3条记录来简化我正在做的事情,2个用于1个人,1个用于另一个.实际上,虽然有超过300,000条记录.

qs.Id = 1的结果为Example.

QuestionSetId       Forename        Surname
-------------------------------------------------------
            1       Bob             Jones

Example的结果与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

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

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

我可以得到sets of individual answers,但不知道如何结合其他人.

我简化的Schema,我无法改变:

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

仅有forename和surname的一些示例数据.

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)

解决方法:

从@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 Fiddle

最后这一个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

这给出了期望的结果.

标签:mysql,aggregate,group-concat
来源: https://codeday.me/bug/20190620/1246533.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有