MYSQL - How to seperate values into columns - concat - mysql

Currently I have the following mysql code entered in phpmyadmin:
select Product_ID, group_concat(`Name` separator ',') as `Spec`
from
(
select Product_ID, concat(`Name`, ':',
group_concat(`Value` separator ',')) as `Name`
from product_spec_list
group by Product_ID, `Name`
) tbl
group by Product_ID
Which produces:
ID Name
3 Shielded:0,Type:General Purpose
4 Shielded:0,Type:General Purpose
etc. with a long list of Product IDs with the Names and Values separated by : and ,.
How do I separate the Values into Columns named by 'Name'?
E.g.
ID Shielded Type
3 0 General Purpose
4 0 General Purpose
There's about 40 different Names of values.
Thanks for any help

I haven't tested it, but I am thinking something like this:
SELECT Product_ID AS `ID`
, GROUP_CONCAT(IF(Name="Shielded", values, "") SEPARATOR "") AS `Shielded`
, GROUP_CONCAT(IF(Name="Type", values, "") SEPARATOR "") AS `Type`
FROM
(SELECT Product_ID, Name, GROUP_CONCAT(value SEPARATOR ',') AS values
FROM product_spec_list
GROUP BY Product_ID, Name
) AS subQ
GROUP BY Product_ID;

Related

mysql query with grouping and concatenate rows into one row

I have the table in mysql with records:
I've written the sql query:
SELECT COUNT(*) AS number_of_contacts, channel_id, direction
FROM cic_case_contacts
WHERE case_id = 328678
GROUP BY channel_id, direction
and the result looks like:
I would like to obtain something like below(based on above data):
I was trying to obtaining that with sql query by using my_sql_function GROUP_CONCAT but it dosen't work:
SELECT COUNT(*) AS number_of_contacts, channel_id, GROUP_CONCAT(direction SEPARATOR ', ') AS directions
FROM cic_case_contacts
WHERE case_id = 328678 AND id IN(149196, 149195, 149194, 149193, 149192) AND `office_id` = 10
GROUP BY channel_id
ORDER BY channel_id
I would be greateful for help.
You can use GROUP_CONCAT on a sub query as follows:
SELECT channelid, GROUP_CONCAT(
CONCAT(direction, ': ', c)
ORDER BY direction
SEPARATOR ', '
) AS summary
FROM (
SELECT channelid, direction, COUNT(*) AS c
FROM t
GROUP BY channelid, direction
) x
GROUP BY channelid
Or simply use conditional aggregation:
SELECT channelid, CONCAT_WS(', ',
CONCAT('in: ', COUNT(CASE WHEN direction = 'in' THEN 1 END)),
CONCAT('out: ', COUNT(CASE WHEN direction = 'out' THEN 1 END))
) AS summary
FROM t
GROUP BY channelid
You can use Concat in MySQL
drop table if exists Demo;
CREATE TABLE Demo
(
ID INT AUTO_INCREMENT PRIMARY KEY,
channelid int,
Name VARCHAR(20)
);
INSERT INTO Demo(channelid, Name)VALUES
(1,'in'),(1,'out'),(1,'in'),(1,'out'),(2,'in'),(2,'out'),(1,'in'),(1,'out'),(1,'in'),(2,'out'),(2,'in'),(2,'out'),(2,'in'),(1,'in'),(1,'in');
Query
SELECT SQL_CALC_FOUND_ROWS
channelid,
group_concat ( concat(name,':',channelid) )
FROM Demo
group by channelid;
SELECT FOUND_ROWS();
See the results the the fiddle
Please find below working code as per your requirement :
select tb.channelid, group_concat
(
concat(tb.name,':',tb.MyCol2Count)
) as v1
from
(Select tbl.channelid,tbl.name,(LENGTH(tbl.val) - LENGTH(REPLACE(tbl.val,",","")) + 1) AS MyCol2Count
from
(SELECT channelid, group_concat
(
concat(name,':',channelid)
) as val,name
FROM Demo
group by channelid,Name) as tbl) as tb group by tb.channelid
You can check on below screenshot : http://springinfosoft.com/code/Groupby_code.png

How to split the string in a single column and arrange the same in the same column in SQL

I have a column as below
Products
jeans,oil
jeans,shampoo
I want to split the strings and use it in the same column using SQL. The result I want is
Products count
jeans 2
oil 1
shampoo 1
Could you please guide me in getting this result
Thank you
You are storing CSV data in your SQL table, which is not a good thing. But it looks like you are trying to move away from that, which is a good thing. Here is one option using a union with SUBSTRING_INDEX:
SELECT Products, COUNT(*) AS count
FROM
(
SELECT SUBSTRING_INDEX(Products, ',', 1) AS Products FROM yourTable
UNION ALL
SELECT SUBSTRING_INDEX(Products, ',', -1) FROM yourTable
) t
GROUP BY Products
ORDER BY
count DESC, Products;
Demo
Firstly you need to split the data into two columns like
SELECT CASE
WHEN name LIKE '%,%' THEN LEFT(name, Charindex(' ', products) - 1)
ELSE name
END,
CASE
WHEN name LIKE '%,%' THEN RIGHT(name, Charindex(' ', Reverse(products)) - 1)
END
FROM YourTable
then you need to union this with the same table... and the final code will look like...
select count( distinct abc), abc from
(
SELECT CASE
WHEN PA_NAME LIKE '% %' THEN LEFT(PA_NAME, Charindex(' ', PA_NAME) - 1)
ELSE PA_NAME
END [abc]
FROM phparty
union all
SELECT CASE
WHEN PA_NAME LIKE '% %' THEN RIGHT(PA_NAME, Charindex(' ', Reverse(PA_NAME)) -1)
END [abc]
FROM phparty
) t group by abc
here you can replace pa_name with your_column_name

Converting column into row using "|" as separators

Please take a look at this Fiddle Example
I want to convert each field into a row from this table:
CREATE TABLE product
(`ID` int, `name` varchar(1), `category` varchar(11), `price` int,`year`int)
;
INSERT INTO product
(`ID`, `name`, `category`, `price`,`year`)
VALUES
(1, 'A', 'Outdoor', 25,2010),
(2, 'A', 'Doll', 34,2009),
(3, 'C', 'Doll', 25,2008),
(4, 'D', 'Outdoor', 20,2010),
(5, 'E', 'Brainteaser', 22,2010),
(6, 'E', 'Brainteaser', 22,2009),
(7, 'G', 'Brainteaser', 30,2009),
(8, 'G', 'Brainteaser', 30,2009)
;
Here's the output I'm trying to get:
field value
name A,C,D,E,G
category Brainteaser,Doll,Outdoor
price 20,22,25,30,34
year 2008,2009,2010
I read a thread about pivoting table with UNION and MAX but I was lost at using MAX with GROUP_CONCAT
SELECT
MAX(CASE WHEN ... GROUP_CONCAT(DISTINCT (value) SEPARATOR '|')) as value
from(
select id,name value, 'name' field
from product
union all
select id,category value, 'category' field
from product
union all
select id,price value, 'price' field
from product
union all
select id,year value, 'year' field
from product
)
GROUP BY field
order by value
Can anyone show me how to get that output?
This will give you expected output:
SELECT 'name' AS `field`. GROUP_CONCAT(DISTINCT `name` ORDER BY `name`) AS `value`
FROM product
UNION ALL
SELECT 'category' AS `field`. GROUP_CONCAT(DISTINCT `category` ORDER BY `category`) AS `value`
FROM product
UNION ALL
SELECT 'price' AS `field`. GROUP_CONCAT(DISTINCT `price` ORDER BY `price`) AS `value`
FROM product
UNION ALL
SELECT 'year' AS `field`. GROUP_CONCAT(DISTINCT `year` ORDER BY `year`) AS `value`
FROM product
Added ORDER BY because looks like you need sorted output
something like this?? Using union all for better proformance and incase there are any dupilcates.
SELECT 'name' field, group_concat(DISTINCT name ORDER BY name SEPARATOR '|') value FROM product
UNION ALL
SELECT 'category' field, group_concat(DISTINCT category ORDER BY category SEPARATOR '|') value FROM product
UNION ALL
SELECT 'price' field, group_concat(DISTINCT price ORDER BY price SEPARATOR '|') value FROM product
UNION ALL
SELECT 'year' field, group_concat(DISTINCT year ORDER BY year SEPARATOR '|') value FROM product;
EDIT:
If you would like to do this with just one query you can achieve it this way.
SELECT
#uName := group_concat(DISTINCT name ORDER BY name SEPARATOR '|'),
#uCat := group_concat(DISTINCT category ORDER BY category SEPARATOR '|') uCat,
#uPrice := group_concat(DISTINCT price ORDER BY price SEPARATOR '|') uPrice,
#uYear := group_concat(DISTINCT year ORDER BY year SEPARATOR '|') uYear
FROM product;
SELECT 'name' field, #uName value
UNION ALL
SELECT 'category' field, #uCat value
UNION ALL
SELECT 'price' field, #uPrice value
UNION ALL
SELECT 'year' field, #uYear value;
NOTE: you can do ORDER BY inside the GROUP_CONCAT
There is a way to complete your request without having to query your table with many queries. In fact, method below is a way to turn any table to pivot. It will use mysql prepared statements for prepare SQL and later execute it:
SELECT
GROUP_CONCAT(f SEPARATOR ' UNION ALL ')
FROM
(SELECT
CONCAT(
'SELECT "',
column_name,
'" AS `field`, GROUP_CONCAT(DISTINCT ',
column_name,
') AS `value` FROM `',
#table_name,
'`'
) AS f
FROM
((SELECT
column_name
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
table_name=#table_name &&
table_schema=#schema_name
) AS fields
CROSS JOIN
(SELECT
#table_name := 'product',
#schema_name:= 'test'
) AS init)
) AS sqldata
The sql above will result in a string, which can be used to assign a variable, like
mysql> SET #sql:=(SELECT GROUP_CONCAT(f SEPARATOR ' UNION ALL ') FROM (SELECT CONCAT('SELECT "', column_name,'" AS `field`, GROUP_CONCAT(DISTINCT ', column_name,') AS `value` FROM `', #table_name, '`') AS f FROM ((SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name=#table_name && table_schema=#schema_name) AS fields CROSS JOIN (SELECT #table_name:='product', #schema_name:='test') AS init)) AS sqldata);
Query OK, 0 rows affected (0.03 sec)
next, prepare:
mysql> PREPARE stmt FROM #sql;
Query OK, 0 rows affected (0.00 sec)
Statement prepared
finally, execute it:
mysql> EXECUTE stmt;
+----------+--------------------------+
| field | value |
+----------+--------------------------+
| ID | 1,2,3,4,5,6,7,8 |
| name | A,C,D,E,G |
| category | Outdoor,Doll,Brainteaser |
| price | 25,34,20,22,30 |
| year | 2010,2009,2008 |
+----------+--------------------------+
5 rows in set (0.00 sec)
The benefit is that you are independent from table structure, field names, e tc. It's a general way - so you may use it to create such pivots for any table.
Few words about variables #table_name and #schema_name. They specify which table and in which schema would be pivoted. In sample above, I used CROSS JOIN to set them in-place, but you may set them separately, to maintain different tables for pivots.

Grouping quantities by price

I have a mysql table like this
id |code|price|quantity
1 |0001|10.00|1
2 |0001|10.00|1
3 |0001|15.00|3
4 |0001|15.00|1
5 |0002| 5.00|2
6 |0002| 5.00|1
Using the functions concat and group_concat I got this result:
SELECT code, group_concat( CONCAT( quantity, 'x', FORMAT(price, 2 ))SEPARATOR '+' ) AS sales
FROM detalle_sales
GROUP BY code
code|sales
0001|1x10,00+1x10,00+3x15.00+1x15.00
0002|2x5.00+1x5.00
How can I group the quantities by the price using mysql?
code|sales
0001|2x10.00+4x15.00
0002|3x5.00
I've done it by php but when the sales field is too long, the result is truncated and gives an inaccurate value.
You need a subquery that groups all the rows with the same price together, then a main query that performs the GROUP_CONCAT by code.
SELECT code, group_concat( CONCAT( quantity, 'x', FORMAT(price, 2 ))SEPARATOR '+' ) AS sales
FROM (
SELECT code, price, SUM(quantity) as quantity
FROM detalle_sales
GROUP by code, price) AS subq
GROUP BY code
DEMO
While I consider it a not-so-good idea to create this sort of format in the DB, here is how it goes:
SELECT code, group_concat( CONCAT( total, 'x', FORMAT(price, 2 ))SEPARATOR '+' ) AS sales
FROM (
SELECT
code, price,
SUM(quantity) AS total
FROM detalle_sales
GROUP BY code, price
) AS baseview
GROUP BY code

Mysql group_concat with sums also inside

I have a table of different attributes I want to sum, and then group concatenate them into a JSON string to make it easier to send over network. Here's a simplified table:
t1
type amount
'atr1' 10
'atr2' 10
'atr1' 17
'atr3' 20
'atr3' 4
I tried something like
select concat('{',
group_concat(
(select concat('"', type, '":', sum(amount)) from t1 group by type)
),
'}')
but failed.
I want to end up with '{"atr1":27,"atr2":10,"atr3":24}'
Try this query -
SELECT CONCAT('{', GROUP_CONCAT(c1), '}') FROM (
SELECT CONCAT('"', type, '":', SUM(amount)) c1 FROM t1 GROUP BY type
) t
something like
select
group_concat(concat('"', type, '":', TheSum))
FROM
(
SELECT SUM(amount) AS TheSum,type
FROM t1
GROUP BY type
) T