Splitting the output of MySQL Group_Concat() - mysql

How do I split Group_Concat() result into different columns? I don't want to show it in the same cell separated by comma.

You can use SUBSTRING_INDEX twice after wrapping it in a subquery, in case you know the delimiter.
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(SomeColumn, '.', 3), '.', -1)
FROM (
SELECT GROUP_CONCAT(...) AS SomeColumn
FROM ...
) AS SomeTable
The first SUBSTRING_INDEX gets the string from first -> n
The second SUBSTRING_INDEX removes the string from first -> n - 1
Check this SQLFiddle example
In your case, if you know the number of columns, your query would look something like (assuming you have 5 strings separated by comma):
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(SomeColumn, '.', 1), '.', -1)
, SUBSTRING_INDEX(SUBSTRING_INDEX(SomeColumn, '.', 2), '.', -1)
, SUBSTRING_INDEX(SUBSTRING_INDEX(SomeColumn, '.', 3), '.', -1)
, SUBSTRING_INDEX(SUBSTRING_INDEX(SomeColumn, '.', 4), '.', -1)
, SUBSTRING_INDEX(SUBSTRING_INDEX(SomeColumn, '.', 5), '.', -1)
FROM (
SELECT GROUP_CONCAT(...) AS SomeColumn
FROM ...
) AS SomeTable

Related

How to select from database using explode

I want export data from my SQL database.
Simply use :
SELECT `id`,`tags` FROM `posts`
This query give me those results :
(1, 'handshake,ssl,windows'),
(2, 'office,word,windows'),
(3, 'site')
I want results in this form:
(1, 'handshake'),
(1, 'ssl'),
(1, 'windows'),
(2, 'office'),
(2, 'word'),
(2, 'windows'),
(3, 'site')
How can write a query that give me this results?
Thank you and sorry for my poor English.
If you are using SQL Server
You can apply the fuction
STRING_SPLIT
SELECT id, value
FROM posts
CROSS APPLY STRING_SPLIT(tags, ',')
Check this out:
SQL Fiddle example
After many search and try finally i find the solution:
SELECT
DISTINCT postid , SUBSTRING_INDEX(SUBSTRING_INDEX(tags, ',', n.digit+1), ',', -1) val
FROM
posts
INNER JOIN
(SELECT 0 digit UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6) n
ON LENGTH(REPLACE(tags, ',' , '')) <= LENGTH(tags)-n.digit;
For a max of three words, the code below can be used. If you want more words then you just add more lines. The method may not be fully automated, but it works.
SELECT id, SUBSTRING_INDEX(SUBSTRING_INDEX(tags, ',', 1), ',', -1) FROM tabela
UNION
SELECT id, SUBSTRING_INDEX(SUBSTRING_INDEX(tags, ',', 2), ',', -1) FROM tabela
UNION
SELECT id, SUBSTRING_INDEX(SUBSTRING_INDEX(tags, ',', 3), ',', -1) FROM tabela
ORDER BY id;

Mysql query with loop

I have this query, works fine for view and csv export from phpmyadmin.
Is possible create a loop without repeat? thanks!
SELECT
id, date, name,
SUBSTRING_INDEX(SUBSTRING_INDEX(message, '-', 1), '(', -1) AS op,
SUBSTRING_INDEX(SUBSTRING_INDEX(message, '-', 4), '-', -3) AS dt,
SUBSTRING_INDEX(SUBSTRING_INDEX(message, ')', 1), '-', -1) AS hour,
SUBSTRING_INDEX(SUBSTRING_INDEX(message, '(', 2), '-', -1) AS note
FROM center
WHERE center.date BETWEEN '2019-08-01 00:00:00' AND '2019-12-31 00:00:00'
and message!= ''
HAVING op = 'op1' OR op = 'op2'
UNION SELECT
id, date, name,
SUBSTRING_INDEX(SUBSTRING_INDEX(message, '-', 6), '(', -1) AS op,
SUBSTRING_INDEX(SUBSTRING_INDEX(message, '-', 9), '-', -3) AS dt,
SUBSTRING_INDEX(SUBSTRING_INDEX(message, ')', 2), '-', -1) AS hour,
SUBSTRING_INDEX(SUBSTRING_INDEX(message, '(', 3), '-', -1) AS note
FROM center
WHERE center.date BETWEEN '2019-08-01 00:00:00' AND '2019-12-31 00:00:00'
and message!= ''
HAVING op = 'op1' OR op = 'op2'
UNION SELECT.... more
You can test this Query. It split a max. of 10 pieces from a row.
SELECT `id`,`date`,`name`,CONCAT('op',`op`) as op,`dt`,`hour`,`note`
,subid,cols -- only for test. you can remove this line
FROM (
SELECT c.id,c.date,c.name,
cnt.*,
-- count the pieces in one row
(LENGTH(message)-LENGTH(replace(message,'(op','')))/3 as cols,
-- Split String in piece and store in #content
#content := SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(' (op ',c.message,' (op'), ' (op', subid+3), ' (op', -1)
, SUBSTRING_INDEX(#content, ' - ',1) as op
, SUBSTRING_INDEX( SUBSTRING_INDEX(#content, ' - ',2), ' - ',-1) as dt
, TRIM( TRAILING ')' FROM SUBSTRING_INDEX( SUBSTRING_INDEX(#content, ' - ',3), ' - ',-1)) as hour
, SUBSTRING_INDEX( SUBSTRING_INDEX(#content, ' - ',4), ' - ',-1) as note
FROM center c
CROSS JOIN (
SELECT 0 as subid UNION ALL SELECT 1 UNION ALL SELECT 2
UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5
UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8
UNION ALL SELECT 9
) as cnt
) as result
WHERE
subid < cols
AND `date` BETWEEN '2019-01-01 00:00:00' AND '2019-12-31 00:00:00'
AND op in (1,2)
ORDER BY id,subid,cols;
Here is a Sample : http://www.sqlfiddle.com/#!9/8bc3b4/60

Select comma separated values from single column

Below is the MySQL data table in which we have 5 lookup columns and their respective names in lookup_list column separated by commas. I want to select each lookup column name separately from lookup_list column like:
Invoice_Lookup as Lookup_1 Name
Leadlist_Lookup as Lookup_2 Name
and so on.
You should normalize your data.
But by using SUBSTRING_INDEX you can split your Lookup_list into columns like so
SELECT
SUBSTRING_INDEX(SUBSTRING_INDEX(Lookup_list, ',', 1), ',', -1) AS Lookup_1
, SUBSTRING_INDEX(SUBSTRING_INDEX(Lookup_list, ',', 2), ',', -1) AS Lookup_2
, SUBSTRING_INDEX(SUBSTRING_INDEX(Lookup_list, ',', 3), ',', -1) AS Lookup_3
, SUBSTRING_INDEX(SUBSTRING_INDEX(Lookup_list, ',', 4), ',', -1) AS Lookup_4
, SUBSTRING_INDEX(SUBSTRING_INDEX(Lookup_list, ',', 5), ',', -1) AS Lookup_5
FROM
[table]

Quartiles query in sql

I have code like this:
SELECT `pelamarmagisterrangkuman`.`major` AS `ProgramStudi`,
count(IPKS1) as N,
AVG(IPKS1) as Mean,
MIN(IPKS1) as Minimum,
MAX(IPKS1) as Maximum,
StdDev(IPKS1) as StDev,
CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(
GROUP_CONCAT(IPKS1 ORDER BY IPKS1 SEPARATOR ','),
',', 50/100 * COUNT(*) + 1), ',', -1) AS decimal) AS `Median`,
CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(
GROUP_CONCAT(IPKS1 ORDER BY IPKS1 SEPARATOR ','),
',', 25/100 * COUNT(*) + 1), ',', -1) AS decimal) AS `Q1`,
CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(
GROUP_CONCAT(IPKS1 ORDER BY IPKS1 SEPARATOR ','),
',', 75/100 * COUNT(*) + 1), ',', -1) AS decimal) AS `Q3`
FROM `pelamarmagisterrangkuman` where `pelamarmagisterrangkuman`.`IPKS1` != 0 and `pelamarmagisterrangkuman`.`TahunDaftar` = 2012 group by `pelamarmagisterrangkuman`.`major`
COUNT, AVG, MIN, MAX, and MIN can work properly. But, quartiles cannot work properly. I mean, the result of the code above is integer values. But, the result that I expected is not just integer value, but also float value because my data is in float and integer value. What may I do to fix that? Thanks in advance
Avoid integers in the arithmetic e.g.
50.0/100.0 * cast(COUNT(*) as decimal) + 1.0

mysql select substrings and group them by column

I am trying to divide data in one onf the tables on my MySQL database.
Column contains data like this:
de:"Sweatjacke*";en:"jacket*";pl:"bluza*";
de:"*";en:"*";pl:"bluza*";
fr:"*";de:"*";en:"*";pl:"dres junior*";cz:"*";
pl:"bluza";
And I am trying to divide all of the translations into separate columns. Already came with solution to do this by using:
SELECT
SUBSTRING_INDEX(SUBSTRING_INDEX(name, ';', 1), ';', -1) as tr1,
SUBSTRING_INDEX(SUBSTRING_INDEX(name, ';', 2), ';', -1) as tr2,
SUBSTRING_INDEX(SUBSTRING_INDEX(name, ';', 3), ';', -1) as tr3,
SUBSTRING_INDEX(SUBSTRING_INDEX(name, ';', 4), ';', -1) as tr4,
SUBSTRING_INDEX(SUBSTRING_INDEX(name, ';', 5), ';', -1) as tr5
FROM product;
statement, but that results in:
tr1 tr2 tr3 tr4 tr5
fr:"*" de:"*" en:"*" pl:"bluza*" cz:"*"
fr:"*" de:"Sweatjacke*" en:"jacket*" pl:"bluza*" cz:"*"
de:"Sweatjacke*" en:"jacket*" pl:"bluza*"
And I want to have the results gruped by translation type (pl/de/en) so in each collumn one type of translatoin is present. For example in column1 = pl:, column2 = en: etc.
Any one came across similar problem and knows a way to solve it?
You need to unpivot the data, then select the first and second part of each value and then re-aggregate it.
However, a better form for the data is really to have language/translation. The following produces this:
select substring_index(tr, ':', 1) as l, substring_index(tr, ':', 2) as t, name
from (select SUBSTRING_INDEX(SUBSTRING_INDEX(name, ';', n.n), ';', -1) as tr, n, name
from product p cross join
(select 1 as n union all select 2 union all select 3 union all select 4 union all
select 5
) n
) n
You would probably want an "id" column or "word" column to identify each row, rather than the name column.
You can now pivot this result to get what you want:
select max(case when l = 'en' then name end) as en,
max(case when l = 'fr' then name end) as fr,
max(case when l = 'de' then name end) as de,
max(case when l = 'pl' then name end) as pl,
max(case when l = 'cz' then name end) as cz
from (select substring_index(tr, ':', 1) as l, substring_index(tr, ':', 2) as t, name
from (select SUBSTRING_INDEX(SUBSTRING_INDEX(name, ';', n.n), ';', -1) as tr, n, name
from product p cross join
(select 1 as n union all select 2 union all select 3 union all select 4 union all
select 5
) n
) n
) lt
group by name;
Managed to solve it by using some of the string related functions funcitons:
SELECT
SUBSTRING_INDEX( SUBSTRING( name, LOCATE( "pl:", name ) , 150 ) , ';', 1 ) AS pl,
SUBSTRING_INDEX( SUBSTRING( name, LOCATE( "en:", name ) , 150 ) , ';', 1 ) AS en,
SUBSTRING_INDEX( SUBSTRING( name, LOCATE( "de:", name ) , 150 ) , ';', 1 ) AS de,
SUBSTRING_INDEX( SUBSTRING( name, LOCATE( "fr:", name ) , 150 ) , ';', 1 ) AS fr
FROM product
Thanks to everyone for help.
As far as I understand you want to UNPIVOT your data. There is no such function in MySQL, so you might want to export your data into MSSQL (you can use free MSSQL Express) and use UNPIVOT function: http://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx