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
Related
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 '; ')
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
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
Is it possible to do something like:
GROUP_CONCAT(user, price SEPARATOR ', ') AS items
The result is John3.99, Mike24.99
What I need is something like:
John - 3.99, Mike - 24.99
Basically use another type of separator for price field.
GROUP_CONCAT(CONCAT(user, ' - ', price) SEPARATOR ', ') AS items
Or just
GROUP_CONCAT(user, ' - ', price SEPARATOR ', ') AS items
Try this way
GROUP_CONCAT(
DISTINCT CONCAT(user,',',Price SEPERATOR)
ORDER BY items
SEPARATOR ';'
)
I have a table like this and I want to select distinct value in single column:
ID Value
1 13245|43558
2 45961|5051
3 43558| 5059
I need output Like this:
13245,43558,45961,5051,5059
try that:
select group_concat(distinct trim(substring_index(substring_index(value, '|', n.n), '|', -1)) separator ',' ) as `values`
from table1 t
cross join (select 1 as n union all select 2 ) n
order by `values`
DEMO HERE
Try this query :
SELECT GROUP_CONCAT(distinct(Value)) from table;