MySQL-多行乘以1的ID并将多列数据转换为逗号分隔的行

时间:2019-03-06 20:39:29

标签: mysql switch-statement group-concat cross-apply

我有一个数据库表:
分隔每个请求的请求者ID列(必需)
类别ID列,可将请求(类别)中的每个项目划分为不同的类别
一个商品ID列,用于分隔类别(itemid)中的每个商品类型
列出项目(项目)名称的项目名称列
一个项目描述符列,该列给出了项目描述(desc)
和金额列,给出该类别中每个项目的总费用(金额)

所以我的桌子看起来像这样:

|---------|-------|----------|--------|-------|------------|
|  reqid  | catid | itemid   | item   | desc  | amount     | 
|---------|-------|----------|--------|-------|------------|
|  1      | 3     | 16       | food   | food  | 200        | 
|---------|-------|----------|--------|-------|------------|
|  1      | 3     | 17       | water  | wtr   | 50         | 
|---------|-------|----------|--------|-------|------------|
|  1      | 3     | 18       | film   | film  | 20         | 
|---------|-------|----------|--------|-------|------------|
|  1      | 5     | 30       | room   | room  | 500        | 
|---------|-------|----------|--------|-------|------------|
|  1      | 5     | 31       | chair  | chair | 150        | 
|---------|-------|----------|--------|-------|------------|
|  2      | 3     | 16       | food   | food  | 200        | 
|---------|-------|----------|--------|-------|------------|
|  2      | 3     | 17       | water  | wtr   | 50         | 
|---------|-------|----------|--------|-------|------------|
|  3      | 3     | 18       | film   | film  | 20         | 
|---------|-------|----------|--------|-------|------------|
|  3      | 5     | 30       | room   | room  | 500        | 
|---------|-------|----------|--------|-------|------------|
|  3      | 5     | 31       | chair  | chair | 150        | 
|---------|-------|----------|--------|-------|------------|

我希望我的查询结果看起来像

|--------|------------------|----------------------|--------------------|--------------------|
| reqid  | catid3itemid     | catid3item           | catid3desc         | catid3amount       | 
|--------|------------------|----------------------|--------------------|--------------------|
|  1     |16, 17, 18        | food, water, film    | food, wtr, film    | 200, 50, 20        | 
|--------|------------------|----------------------|--------------------|--------------------|
|  2     |16, 17            | food, water          |food, wtr           | 200, 50,           | 
|--------|------------------|----------------------|--------------------|--------------------|
|  3     |18                | film                 | film               | 20                 | 
|--------|------------------|----------------------|--------------------|--------------------|

续:

|------------------|----------------------|--------------------|--------------------|
| catid4itemid     | catid4item           | catid4desc         | catid4amount       | 
|------------------|----------------------|--------------------|--------------------|
|                  |                      |                    |                    | 
|------------------|----------------------|--------------------|--------------------|
|                  |                      |                    |                    | 
|------------------|----------------------|--------------------|--------------------|
|                  |                      |                    |                    | 
|------------------|----------------------|--------------------|--------------------|

续决赛:

|------------------|----------------------|--------------------|--------------------|
| catid5itemid     | catid5item           | catid5desc         | catid5amount       | 
|------------------|----------------------|--------------------|--------------------|
|30,31             |room, chair           |room, chair         | 500, 150           | 
|------------------|----------------------|--------------------|--------------------|
|                  |                      |                    |                    | 
|------------------|----------------------|--------------------|--------------------|
|30,31             |room, chair           |room, chair         | 500, 150           | 
|------------------|----------------------|--------------------|--------------------|

我一直在看有关使用的帖子 GROUP_CONCAT或交叉申请或开关声明

例如GROUP_CONCAT:

select *, GROUP_CONCAT(`table`.`categoryid` ORDER BY `table`.`categoryid` ASC SEPARATOR ', ') AS `categoryid`
from `table` 
GROUP BY `table`.`requestid`

但是这会将所有内容都集中到一列中,该列不由category ID分隔,而是将所有类别ID集中在一起。

任何建议或帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

谢谢大家的帮助!我没有使用数据透视表就知道了

选择tablerequestidrequest_id, group_concat((({tablecategoryid = 2时然后tableitem结尾)分隔符',')AS item2 ,group_concat(((({tablecategoryid = 2时为tabledescriptor结尾)分隔符',')AS descriptor2, group_concat((({tablecategoryid = 2时然后tableamount结尾)分隔符',')AS amount2 group_concat((({tablecategoryid = 3时然后tableitem结尾)分隔符',')AS item3 group_concat((({tablecategoryid = 3时然后tabledescriptor结尾)分隔符',')AS descriptor3 group_concat((当(tablecategoryid = 3时然后tableamount结尾)分隔符',')AS amount3 group_concat((({tablecategoryid = 4时然后tableitem结尾)分隔符',')AS item4 group_concat((({tablecategoryid = 4时然后tabledescriptor结尾)分隔符',')AS descriptor4 group_concat((({tablecategoryid = 4时然后tableamount结尾)分隔符',')AS amount4 group_concat((({tablecategoryid = 5时然后tableitem结尾)分隔符',')AS item5 group_concat((({tablecategoryid = 5时然后tabledescriptor结尾)分隔符',')AS descriptor5 group_concat((当(tablecategoryid = 5时然后tableamount结尾)分隔符',')AS amount5

来自table

其中(({tablecategoryid = 2)或 (tablecategoryid = 3)或 (tablecategoryid = 4)或 (tablecategoryid = 5))

table分组。requestid

答案 1 :(得分:0)

如果类别是固定的(3、4和5),则可以使用以下查询:

select 
reqid,
group_concat(distinct if(catid = 3, itemid, null)) as catid3itemid, 
group_concat(distinct if(catid = 3, item, null)) as catid3item, 
group_concat(distinct if(catid = 3, `desc`, null)) as catid3desc, 
group_concat(distinct if(catid = 3, amount, null)) as catid3amount , 
group_concat(distinct if(catid = 4, itemid, null)) as catid4itemid, 
group_concat(distinct if(catid = 4, item, null)) as catid4item, 
group_concat(distinct if(catid = 4, `desc`, null)) as catid4desc, 
group_concat(distinct if(catid = 4, amount, null)) as catid4amount , 
group_concat(distinct if(catid = 5, itemid, null)) as catid5itemid, 
group_concat(distinct if(catid = 5, item, null)) as catid5item, 
group_concat(distinct if(catid = 5, `desc`, null)) as catid5desc, 
group_concat(distinct if(catid = 5, amount, null)) as catid5amount 
from tab 
group by reqid;


如果必须是动态的,则可以使用过程。下面,我使用了重复结构来生成查询,该查询返回每个catid(最小到最大)所需的结构,并使用branchless code执行它:

-- only to avoid problem with only_full_group_by
set global sql_mode = "";

create table tab (reqid int, catid int, itemid int, item varchar(10), `desc` varchar(20), amount int);
insert into tab values
(1, 3, 16, 'food', 'food', 200),
(1, 3, 17, 'water', 'wtr', 50),
(1, 3, 18, 'film', 'film', 20),
(1, 5, 30, 'room', 'room', 500),
(1, 5, 31, 'chair', 'chair', 150),
(2, 3, 16, 'food', 'food', 200),
(2, 3, 17, 'water', 'wtr', 50),
(3, 3, 18, 'film', 'film', 20),
(3, 5, 30, 'room', 'room', 500),
(3, 5, 31, 'chair', 'chair', 150);

delimiter $$
CREATE PROCEDURE result()
BEGIN

    DECLARE i INT DEFAULT (select min(catid) from tab);
    DECLARE iEnd INT DEFAULT (select max(catid) from tab);

    SET @sQuery = 'select reqid';

    WHILE i <= iEnd DO

        set @sQuery = CONCAT(@sQuery, 
            ', group_concat(distinct if(catid = ',i,', itemid, null)) as catid',i,'itemid,
            group_concat(distinct if(catid = ',i,', item, null)) as catid',i,'item, 
            group_concat(distinct if(catid = ',i,', `desc`, null)) as catid',i,'desc, 
            group_concat(distinct if(catid = ',i,', amount, null)) as catid',i,'amount'
        );

        SET i = i + 1;
    END WHILE; 

    SET @sQuery = CONCAT(@sQuery, ' from tab group by reqid');

    PREPARE stmt FROM @sQuery;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;

END $$


call result();


注意:因为您没有提供太多详细信息,而且正如注释中所述,所以最好在应用程序中执行显示逻辑。