I have a database table:
requesting persons ID column that separates each request (reqid)
category ID column that separates into different categories each item that's in the request (catid)
an item ID column that separates each item type within the category (itemid)
an item name column that lists the name of the item (item)
an item descriptor column that gives a description of the item (desc)
and amount column that gives the total cost of each item in that category (amount)
so my table looks like this:
|---------|-------|----------|--------|-------|------------|
| 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 |
|---------|-------|----------|--------|-------|------------|
And i want my query result to look like
|--------|------------------|----------------------|--------------------|--------------------|
| 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 |
|--------|------------------|----------------------|--------------------|--------------------|
continued:
|------------------|----------------------|--------------------|--------------------|
| catid4itemid | catid4item | catid4desc | catid4amount |
|------------------|----------------------|--------------------|--------------------|
| | | | |
|------------------|----------------------|--------------------|--------------------|
| | | | |
|------------------|----------------------|--------------------|--------------------|
| | | | |
|------------------|----------------------|--------------------|--------------------|
continued final:
|------------------|----------------------|--------------------|--------------------|
| catid5itemid | catid5item | catid5desc | catid5amount |
|------------------|----------------------|--------------------|--------------------|
|30,31 |room, chair |room, chair | 500, 150 |
|------------------|----------------------|--------------------|--------------------|
| | | | |
|------------------|----------------------|--------------------|--------------------|
|30,31 |room, chair |room, chair | 500, 150 |
|------------------|----------------------|--------------------|--------------------|
I've been seeing posts about using GROUP_CONCAT or CROSS APPLY or SWITCH STATEMENT
For instance GROUP_CONCAT:
select *, GROUP_CONCAT(`table`.`categoryid` ORDER BY `table`.`categoryid` ASC SEPARATOR ', ') AS `categoryid`
from `table`
GROUP BY `table`.`requestid`
but this lumps everything into a column not separated by the category id , but all the category ids together in one column.
Any suggestions or help would be much appreciated.
thank you all for the help! i figured it out without using pivot tables
select table
. requestid
AS request_id
, group_concat((case when ( table
. categoryid
= 2) then table
. item
end) separator ',') AS item2
,group_concat((case when ( table
. categoryid
= 2) then table
. descriptor
end) separator ',') AS descriptor2
, group_concat((case when ( table
. categoryid
= 2) then table
. amount
end) separator ',') AS amount2
, group_concat((case when ( table
. categoryid
= 3) then table
. item
end) separator ',') AS item3
, group_concat((case when ( table
. categoryid
= 3) then table
. descriptor
end) separator ',') AS descriptor3
, group_concat((case when ( table
. categoryid
= 3) then table
. amount
end) separator ',') AS amount3
group_concat((case when ( table
. categoryid
= 4) then table
. item
end) separator ',') AS item4
, group_concat((case when ( table
. categoryid
= 4) then table
. descriptor
end) separator ',') AS descriptor4
, group_concat((case when ( table
. categoryid
= 4) then table
. amount
end) separator ',') AS amount4
group_concat((case when ( table
. categoryid
categoryid
= 5) then table
. item
end) separator ',') AS item5
, group_concat((case when ( table
. categoryid
= 5) then table
. descriptor
end) separator ',') AS descriptor5
, group_concat((case when ( table
. categoryid
= 5) then table
. amount
end) separator ',') AS amount5
from table
where (( table
. categoryid
= 2) or ( table
. categoryid
= 3) or ( table
. categoryid
= 4) or ( table
. categoryid
= 5))
group by table
. requestid
If the categories were fixed (3, 4 and 5) you could use this query:
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;
If it has to be dynamic, a procedure can be used. Below I have used a repetition structure to generate a query that returns the desired structure for each catid
(minimum to maximum) and executes it with prepared statment :
-- 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();
Note: Because you did not give too many details and as has already been said in the comments, it might be better to perform the display logic in the application.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.