2012-12-06 89 views
4

我從通用問題/答案數據中獲取名稱和地址數據以創建某種標準化的報告數據庫。MySQL Query GROUP_CONCAT Over Multiple Row

我得到的查詢使用了group_concat,它適用於單個問題集,但不適用於多個集。

我試圖簡化我在做什麼,只用姓和名,只有3條記錄,2個爲1個人,1個爲另一個。實際上雖然有超過30萬條記錄。

Example結果與qs.Id = 1

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

結果與qs.Id IN (1, 2, 3)Example

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但不知道如何將他人相結合。

我了簡化的架構,我不能改變:

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) 
+1

+1寫得很好的問題,我會推薦的一件事就是把你的查詢從SQL小提琴放在這個網站上。在這種情況下,sql fiddle已關閉,我們無法訪問您已經編寫的查詢。 :) – Taryn

+0

+1的確是一個非常複雜的問題 –

+0

'+ 1'確實! :D –

回答

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

其給出所期望的結果。

+0

完美 - 我想!我會在主要解決方案上嘗試一下,謝謝。 – PeteGO

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; 

OR

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 ; 

OR

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 ; 
+0

+1令人難以置信的快速 –

+0

感謝您的快速反應,但我真的希望每個答案在一個單獨的列。 – PeteGO