MySQL 透视 Table 和编号列
MySQL Pivot Table and Numbered Columns
我正在处理一个查询,该查询将采用 table,并使用动态 SQL 将其作为枢轴 table 加入。我已经在 Stack Overflow 以及互联网的其他部分阅读了一些问题,但未能找到解决我想要完成的问题的方法。
我有一个table像这样
+---------------------------------------+
| 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 |
+---------------------------------------+
然后像这样连接table自身(别问我为什么要连接自身,不是我设计的)
+-----------------------------------+
| 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 和一个工作示例。
在此先感谢您的帮助,期待这项工作!
here 中的存储过程将为您生成 SQL。
我可以使用它来处理这个查询,但它有点耗费性能,所以我可能会为此切换到 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;
我正在处理一个查询,该查询将采用 table,并使用动态 SQL 将其作为枢轴 table 加入。我已经在 Stack Overflow 以及互联网的其他部分阅读了一些问题,但未能找到解决我想要完成的问题的方法。
我有一个table像这样
+---------------------------------------+
| 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 |
+---------------------------------------+
然后像这样连接table自身(别问我为什么要连接自身,不是我设计的)
+-----------------------------------+
| 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 和一个工作示例。
在此先感谢您的帮助,期待这项工作!
here 中的存储过程将为您生成 SQL。
我可以使用它来处理这个查询,但它有点耗费性能,所以我可能会为此切换到 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;