mySQL GROUP_CONCAT different Separator each x results - mysql

in mySQL query is an
GROUP_CONCAT(fieldname SEPARATOR ', ')
But field with should not be too long.
Therefore I want a different Separator after x datasets (i.e. each 3rd separator should be '\n')
I would be happy to get help for this.
Thanks!

This is a real pain. One method uses lead() to bring three values together and then filter the values to every third one:
select x,
group_concat(col_3 separator '; ')
from (select t.x,
concat_ws(', ',
col,
lead(col, 1) over (order by ?),
lead(col, 2) over (order by ?)
) as col_3
row_number() over (partition by x order by ?) as seqnum
from t
) t
where mod(seqnum, 3) = 1
group by x;
If you want other aggregations, you can filter in the group_concat() instead:
select x,
group_concat(case when mod(seqnum, 3) = 1 then col_3 end separator '; ')

Related

Can I concatenate multiple MySQL Column into One Column?

Good day i would like to ask if this is possible in MySQL
SELECT id,label,name,age,sex FROM table LIMIT 3
Output
[row1] id,label,name,age,sex
[row2] id,label,name,age,sex
[row3] id,label,name,age,sex
My Output Needed
[row1] id
[row2] label
[row3] name
[row4] age
[row5] sex
[row6] id
[row7] label
[row8] name
[row9] age
[row10] sex
[row11] id
[row12] label
[row13] name
[row14] age
[row15] sex
You can do something like this:
SELECT * FROM
((SELECT id AS id1, 1 AS rownum, 'id' AS colname, id AS Data_value FROM mytable LIMIT 3)
UNION ALL
(SELECT id, 2, 'label', label FROM mytable LIMIT 3)
UNION ALL
(SELECT id, 3, 'name', name FROM mytable LIMIT 3)
UNION ALL
(SELECT id, 4, 'age', age FROM mytable LIMIT 3)
UNION ALL
(SELECT id, 5, 'sex', sex FROM mytable LIMIT 3)) A
ORDER BY id1, rownum
Here's a fiddle: https://www.db-fiddle.com/f/dvg6x1vBg6H5bDNp9VZxQa/4
I've added 3 additional column id AS id1, rownum and colname. The first two additional column is used for ORDER BY at the outer query. If you don't want to see the additional column, you can just type SELECT Data_value FROM ... at the outer query.
You can use group_concat() to aggregate rows by string concatenation. For the LIMIT to work you then need to use a derived table. But you should be careful with a LIMIT without an ORDER BY. As the order of a query result can be random unless an explicit ORDER BY is issued, you may get different results each time you run the query.
SELECT group_concat(id,
'\n',
label,
'\n',
name,
'\n',
age,
'\n',
sex
SEPARATOR '\n')
FROM (SELECT id,
label,
name,
age,
sex
FROM elbat
LIMIT 3) x;
If you just want to concatenate the columns but keep the rows just use concat().
SELECT concat(id,
'\n',
label,
'\n',
name,
'\n',
age,
'\n',
sex)
FROM elbat
LIMIT 3;
yes,you can use union all like below :
SELECT id FROM table LIMIT 3
union all
SELECT label FROM table LIMIT 3
union all
SELECT name FROM table LIMIT 3
union all
SELECT age FROM table LIMIT 3
union all
SELECT sex FROM table LIMIT 3
That what you looking is to Unpivot data. For more info about pivot and unpivot you can check here.
http://archive.oreilly.com/oreillyschool/courses/dba1/dba110.html
Unfortunately there is no easy way to unpivot in mysql.
The below script will work for MySQL 8.0
set #rowNum :=0;
set #string :=(
select group_concat(id,',',label,',',name,',',age,',',sex separator ',')
from (
select id, label, name, age, sex from mytable limit 3
) x
);
with recursive
R1 as ( select #string as items),
R2 as ( select 1 as n
union
select n + 1 from R2, R1
where n <= length(items) - length(replace(items, ',', '')))
select distinct #rowNum := #rowNum+1 as rowNum, substring_index(substring_index(items, ',', n), ',', -1) output from R2, R1;

Mysql how to search the result of a select statement

I have the following query.
SELECT
horse_name AS Horse_Name,
GROUP_CONCAT(
placing_numerical
ORDER BY
race_date
DESC SEPARATOR
', '
) Place
FROM
results
GROUP BY
Horse_Name
I would then like to search the results of Place with a LIKE '%xyz%' query. Is there a way to do this in the same query?
Thanks for lokking.
One way is with a subquery
select *
from (
SELECT horse_name AS Horse_Name,
GROUP_CONCAT( placing_numerical ORDER BY race_date DESC SEPARATOR ', ' ) Place
) tbl
Where tbl.Place like '%xyz%'
SELECT
*
FROM
(
SELECT
horse_name AS Horse_Name,
GROUP_CONCAT(
placing_numerical
ORDER BY
race_date
DESC SEPARATOR
', '
) Place
FROM
results
GROUP BY
Horse_Name
) tbl
WHERE
tbl.Place LIKE '%xyz%'
Thanks to Jacob, this works a treat and I now understand more about subqueries.

MySQL Join Query Autogenerate Serial Number

My Following Query gives the result according to my record but what i have the problem is my query is generating some different serial number .Anyways i need the serial number to start from 1 but this query is join query is shows different serial number like i can say during joining it skips the series .
Kindly help to generate the series from 1 to number of rows from db without skipping the series in between. Thanks in Advance
SELECT
#a:=#a+1 sno,
p.po_no as id,
DATE_FORMAT(p.po_date, '%d-%m-%Y') as po_date,
p.customer,
p.cust_po as po_no,
p.tot_ord_qty,
DATE_FORMAT(p.delivery_date, '%d-%m-%Y') AS delivery_date,
p.dc_status,
p.inv_status,
p.tot_dc_qty,
p.tot_inv_qty,
COALESCE(GROUP_CONCAT(distinct d.dc_no SEPARATOR ', '), 0) as dc,
GROUP_CONCAT( d.active SEPARATOR ', ') as status
FROM (SELECT #a:= 0) AS a, po_header p
LEFT JOIN dc_details d
ON p.cust_po = d.cust_po
group by
p.cust_po
Result:
The reason you're skipping numbers is because of GROUP BY. Grouping is done after the serial numbers are generated, so it combines all the rows with the same cust_po and you only see one of the serial numbers.
Move the grouping into a subquery and add the serial numbers in the main query.
SELECT #a := #a+1 AS sno, t.*
FROM (SELECT #a := 0) AS a
CROSS JOIN (
SELECT p.po_no as id,
DATE_FORMAT(p.po_date, '%d-%m-%Y') as po_date,
p.customer,
p.cust_po as po_no,
p.tot_ord_qty,
DATE_FORMAT(p.delivery_date, '%d-%m-%Y') AS delivery_date,
p.dc_status,
p.inv_status,
p.tot_dc_qty,
p.tot_inv_qty,
COALESCE(GROUP_CONCAT(distinct d.dc_no SEPARATOR ', '), 0) as dc,
GROUP_CONCAT( d.active SEPARATOR ', ') as status
FROM po_header AS p
LEFT JOIN dc_details AS d ON p.cust_po = d.cust_po
GROUP BY p.cust_po
ORDER BY p.cust_po) AS t

GROUP_CONCAT numbering

is it possible to have numbering in GROUP_CONCAT
like
If, from GROUP_CONCAT(empnam SEPARATOR ', ')
I get a set,
< JohnM, DannyP, TiffnyK, KarlM >
I need to have
< 1.JohnM, 2.DannyP, 3.TiffnyK, 4.KarlM >
I tried following, but didnt get desired results.
SET #x:=0;
SELECT
GROUP_CONCAT(#x:=#x+1,' ', s.empnam SEPARATOR ', ') AS emps, #x:=0
< tables >
< filters >
is it possible at Query-Level, or I have to do it at Application Side ?
Years later, we should abandon mutating variables inside a select statement, as since MySQL 8 we can use the standard way, with window functions:
with base as (
select dep,
empnam,
count(*) over (partition by dep order by empnam) num
from t)
select dep,
group_concat(concat(num, '.', empnam) separator ', ') emps
from base
group by dep
See db-fiddle
Original answer (2016)
You can do this on the application side, but in MySQL 5.7 it is possible. In the following query, I assume you group the names by something, for example their department (I called it dep). This in order to illustrate that the counter starts from 1 for every new group.
select dep,
group_concat(
concat(#i := if (#grp = dep, #i + 1, if(#grp := dep,1,1)), '.', empnam)
separator ', ') emps
from t,
(select #i := 0, #grp := '') init
group by dep;
See SQL fiddle
or db-fiddle.
Make sure to put your table name in the from clause, and to use the actual field you want to group by. If you have multiple fields to group by, the expression assigned to #i will need to change. You could for instance concatenate the values that define a group.
By using a separator of two characters you ensure to have a space between each name.
Try this:
SET #x:=0;
SELECT
GROUP_CONCAT(CONCAT(#x:=#x+1, '.', s.empnam) SEPARATOR ', ') AS emps, #x:=0
< tables >
< filters >

SQL Concatenating distinct values from multiple columns into one row

I have this 3 columns tab
PRODUCT....CATEGORY......CLASS
X............1.............II
Y............1.............II
Z............1.............II
Y............2.............II
And I want to return a single row with all DISTINCT values of each column:
RESULT
X Y Z 1 2 II
What's the best way to get this result?
Assuming there are no duplicates between the columns, you can use group_concat():
select concat_ws(' ',
group_concat(distinct product separator ' '),
group_concat(distinct category separator ' '),
group_concat(distinct class separator ' ')
)
from tab t;
You can first collect all values in a subselect and then show these values with group_concat
select group_concat(v separator ' ')
from (select product as v from testa
union
select category as v from testa
union
select class as v from testa) t
SQLFiddle