MySQL数据透视表和编号列

时间:2015-04-20 19:37:38

标签: mysql sql pivot-table

我正在处理将采用表的查询,并使用动态SQL将其作为数据透视表加入。我已经在Stack Overflow以及其他互联网上阅读了一些问题,并且无法找到我想要完成的解决方案。

我有一张像这样的桌子

+---------------------------------------+
| ID   First_name    Last_name    owner |
+---------------------------------------+
| 1    Joe           Bob          1     |
| 2    Fluffy        Bob          0     |
| 3    Killer        Bob          0     |
| 4    Bob           Joe          1     |
| 5    Yapper        Bob          0     |
+---------------------------------------+

这样的连接表就是这样(不要问我为什么它会自己加入,我没有设计它)

+-----------------------------------+
| contact_id    relation_contact_id |
+-----------------------------------+
| 1             2                   |
| 1             3                   |
| 4             5                   |
+-----------------------------------+

因此,每个用户都有可能拥有一只或多只宠物。我需要的枢轴是每个所有者的宠物名称,我希望它被编号(即Pet1_name,Pet2_name等)像这样

+---------------------------------------------------+
| First_name    Last_name    Pet1_name    Pet2_name |
+---------------------------------------------------+
| Joe           Bob          Fluffy       Killer    |
| Bob           Joe          Yapper       NULL      |
+---------------------------------------------------+

我在这里遇到的主要问题是让数字正常运行。目前,它在每行之后不会重置为0,因此我将获得一堆空条目。使用上面的数据,这是我的结果集当前的样子:

+----------------------------------------------------------------+
| First_name    Last_name    Pet1_name    Pet2_name    Pet3_name |
+----------------------------------------------------------------+
| Joe           Bob          Fluffy       Killer       NULL      |
| Bob           Joe          NULL         NULL         Yapper    |
+----------------------------------------------------------------+

这是我正在运行的SQL

SET @sql = NULL;
SET @counter = 0;
Select GROUP_CONCAT(distinct
CONCAT('MAX(case when c2.id = ''', cc.relation_contact_id, 
       ''' AND c.id = ''', cc.contact_id, ''' 
       then c2.first_name end) AS ', CONCAT('`Pet_', @counter := @counter + 1, '_Name`')
)) INTO @sql
From contacts_contacts as cc;
SET @counter = 0;

SET @sql = CONCAT('SELECT c.id, c.first_name, c.last_name, c.email, ', @sql, '
FROM contacts c 
LEFT JOIN contacts_contacts cc on c.id = cc.contact_id 
LEFT JOIN contacts c2 on c2.id = cc.relation_contact_id
WHERE c.owner = 1
GROUP BY c.id
');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

这是一个SQLFiddle,其中有一个工作示例。

提前感谢您的帮助,期待这项工作!

2 个答案:

答案 0 :(得分:0)

我得到了它来处理这个查询,但它有点性能,所以我可能会切换到PHP。在this question上找到了我的答案,所以有人可以将其标记为Dupe,如果他们愿意的话。

与此同时,这里有link to the updated SQLFiddle查询有效。

SET @sql = NULL;
Select 
  GROUP_CONCAT(distinct
    CONCAT('max(case when rownum = ', 
           rownum, 
           ' then c2.first_name end) AS Pet_', rownum, '_Name'
    )
  ) INTO @sql
from
(  
  select contact_id, relation_contact_id,
    @row:=if(@prev=contact_id, @row,0) + 1 as rownum,
    @prev:=contact_id 
  from contacts_contacts, (SELECT @row:=0) r
) cc;

SET @sql = CONCAT('SELECT c.id, c.first_name, c.last_name, c.email as e, ', @sql, '
FROM
(
  select contact_id, relation_contact_id,
    @row:=if(@prev=contact_id, @row,0) + 1 as rownum,
    @prev:=contact_id 
  from contacts_contacts, (SELECT @row:=0) r
) cc
LEFT JOIN contacts c on c.id = cc.contact_id 
LEFT JOIN contacts c2 on c2.id = cc.relation_contact_id
WHERE c.owner = 1
GROUP BY e
');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

答案 1 :(得分:-1)

here中的存储过程将为您生成SQL。