How to sum a comma separated string in SQL? [duplicate] - mysql

This question already has answers here:
Summing a comma separated column in MySQL 4 (not 5)
(4 answers)
Closed 9 years ago.
id value
1 1,2,3,4
2 2,3,4
So I want to get this result:
id sum
1 10
2 9
Can I do it in SQL(MySQL)?

With great effort, you can do this. Really, though, this is a very, very bad way to store data.
In the spirit that sometimes we have to use data whose format is not under our control:
select id,
(substring_index(value, ',', 1) +
substring_index(substring_index(concat(value, ',0'), ',', 2), ',', -1) +
substring_index(substring_index(concat(value, ',0'), ',', 3), ',', -1) +
substring_index(substring_index(concat(value, ',0'), ',', 4), ',', -1) +
substring_index(substring_index(concat(value, ',0'), ',', 5), ',', -1)
) as thesum
from t;
The nested called to substring_index() fetch the nth value in the string. The concat(value, ',0') is to handle the case where there are fewer values than expressions. In this case, the nested substring_index() will return the last value for any value of n greater than the number of items in the list. Concatenating 0 to the list ensures that this doesn't affect the sum.
The SQL Fiddle is here.

you can do it more dynamically Creating a function. Please follow the following steps
create a function that give the sum of a comma separated value
CREATE FUNCTION GetToalOfCommaSeperatedVal
(
#commaSeperatedVal varchar(100)
)
RETURNS int
AS
BEGIN
declare #sum int
DECLARE #x XML
SELECT #x = CAST('<A>'+ REPLACE(#commaSeperatedVal,',','</A><A>')+ '</A>' AS XML)
SELECT #sum=sum(t.value('.', 'int'))
FROM #x.nodes('/A') AS x(t)
return #sum
END
GO
the do a just select command in the following way
select id,dbo.GetToalOfCommaSeperatedVal(value) from YOUR_TABLE

Related

How to convert comma separated string value into rows in MySQL? [duplicate]

This question already has answers here:
What is the opposite of GROUP_CONCAT in MySQL?
(6 answers)
Split comma separated string into rows in mysql
(3 answers)
Closed 4 months ago.
I have one column in MySQL which is return me comma separated value , I want to convert that column in to rows.
Better answer then How to convert comma separated parameters to rows in mysql?
select value from table limit 1
response
value
honda,activa,pleasure,car
I want this value to row like
value
honda
activa
pleasure
car
CREATE TABLE response (id INT, value TEXT)
SELECT 1 id, 'honda,activa,pleasure,car' value;
SELECT response.id, jsontable.value
FROM response
CROSS JOIN JSON_TABLE(CONCAT('["', REPLACE(value, ',', '","'), '"]'),
'$[*]' COLUMNS (value TEXT PATH '$')) jsontable;
id
value
1
honda
1
activa
1
pleasure
1
car
fiddle
PS. The query assumes that the value does not contain duoble quotes. If they are present then they must be quoted. See https://dbfiddle.uk/HUmPZEo1
First we need to create function which return index value of comma separated value
CREATE FUNCTION `SPLIT_STR`(
x VARCHAR(255),
delim VARCHAR(12),
pos INT
) RETURNS varchar(255) CHARSET utf8mb3
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
delim, '')
Then Create virtual recursive table from current value
with recursive new_table as (
select value ,LENGTH(t.value) - LENGTH(REPLACE(t.value, ',', '')) as n ,1 as x from table t limit 1
union all
select value, n,1+x as x from new_table where x <= n
)
select TRIM(SPLIT_STR(value,',',x)) as value from new_table
will return
value
honda
activa
pleasure
car

MySQL group by comma seperated list unique [duplicate]

This question already has answers here:
Is storing a delimited list in a database column really that bad?
(10 answers)
Closed 2 years ago.
The column textfield has comma-seperated list values
ID | textfield
1 | english,russian,german
2 | german,french
3 | english
4 | null
I'm attempting to count the amount of languages in textfield. The default language is "English", so if null then "English". The correct amount of languages is 4(english,russian,german,french).
Here is my query to attempt doing this:
SELECT SUM((length(`textfield`) - length(replace(`textfield`, ',', '')) + 1)) as my
FROM yourtable;
The result i get is 6, i don't know how to group the languages.
Here is fiddle
http://sqlfiddle.com/#!9/0e532/1
The desired result is 4. How do i solve?
Identifying the source of error
What your query is doing is counting how many languages in each row, and adding them all together. Your query does not take into account duplicates. Since English shows up twice in the table, it is counted twice (and German, too), hence in your example six. Also, another issue is that your current code considers null as what null truly means, the absence of a value.
For example, if your database was
ID | textfield
---|----------
1 | null
you would also be arriving at incorrect results (more on this below).
Solution
This gets you a comma separated result of the languages, no duplicates.
SELECT
GROUP_CONCAT(DISTINCT SUBSTRING_INDEX(SUBSTRING_INDEX(textfield, ',', n.digit+1), ',', -1)) textfield
FROM
yourtable
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(textfield, ',', '')) <= LENGTH(textfield)-n.digit;
This query can serve as a subquery for what you were attempting to do in the question prompt. In other words, instead of the length('textfield') ... you would provide the resulting column name from this query
Null as in English
This logic should not be implemented at the database level, IMHO. If you want to go ahead and consider null entries as English, that is fine. The downside is the example I provided for you before. When you have a query that solves for the total languages in the database, if English wasn't an explicitly stated language and instead just a null value, then the query wouldn't 'count' English (it's null). But you can't just add 1 every time you find the amount of languages because English might already be explicit.
Recommendations:
Avoid comma separated lists in databases by normalizing your data
No value makes sense for a null field
For version 5.6 (like in the fiddle)
SELECT COUNT(DISTINCT SUBSTRING_INDEX(SUBSTRING_INDEX(languages.textfield, ',', numbers.num), ',', -1)) languages_count
FROM (SELECT COALESCE(textfield, 'english') textfield
FROM yourtable) languages
JOIN (SELECT 1 num UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) numbers
ON numbers.num <= LENGTH(languages.textfield) - LENGTH(REPLACE(languages.textfield, ',', '')) + 1;
fiddle
For version 8.x (as claimed in a comment)
SELECT COUNT(DISTINCT jsontable.value) languages_count
FROM yourtable
CROSS JOIN JSON_TABLE( CONCAT('["', REPLACE(COALESCE(textfield, 'english'), ',', '","'), '"]'),
"$[*]" COLUMNS( value VARCHAR(254) PATH "$" )
) AS jsontable;
fiddle

Find all numbers that are present more then 3 times in a column of CSVs

I basically want this: if certain number is present >= 3 times then do some action ...
My table's column is this:
As you can see here that number 38 is present >= 3 times in absent_sids column, so I want to have some actions on him like ban or something else. But I don't know what sql query should I write because;
1. I am quite new to php/mysql
2. The column has comma separated numbers, and its quite difficult for me to search in this column through mysql query and bring the absent_sid that is >= 3 times in a given period of time/date.
Plz help
This is quite long but working. Steps: 1) convert the array into rows using CHAR_LENGTH and REPLACE function. 2) Use GROUP BY and HAVING COUNT to search for numbers that exists 3 or more times
See demo here: http://sqlfiddle.com/#!9/39afc0/2
SELECT absent_sids
from (
SELECT
tablename.aid,
SUBSTRING_INDEX(
SUBSTRING_INDEX(
tablename.absent_sids, ',', numbers.n), ',', -1) as absent_sids
FROM
(select ORDINAL_POSITION as n
from INFORMATION_SCHEMA.COLUMNS
where table_name='COLUMNS'
and ORDINAL_POSITION <= (
select round(max(length(absent_sids))/2)
from tablename)) numbers
INNER JOIN tablename
ON CHAR_LENGTH(tablename.absent_sids)
-CHAR_LENGTH(REPLACE(tablename.absent_sids, ',', ''))
>= numbers.n-1) tab
GROUP BY absent_sids
HAVING COUNT(*) >= 3

sql new column by delimiter with order ID

Hi this maybe a simple one but I need help specifically for MYsql
I have the data in one column lets call the column WORK 1,2,3,5,2 (these values are sometimes longer and shorter or more values are present e.g 12,15,11,15,16,143)
I need these to be put into 1 new column for each delimiter and have an ID for the order presented. e.g output
SELECT
*
FROM (SELECT
ROW_NUMBER()
OVER (ORDER BY WORK) AS Row,
RIGHT(LEFT(T.WORK, Number - 1),
CHARINDEX(',', REVERSE(LEFT(',' + T.WORK, Number - 1)))) AS a
FROM master..spt_values,
<YOUR_TABLENAME> T
WHERE Type = 'P'
AND Number BETWEEN 1 AND LEN(T.WORK) + 1
AND (SUBSTRING(T.WORK, Number, 1) = ','
OR SUBSTRING(T.WORK, Number, 1) = '')) AS A

Mysql - count values from comma-separated field [duplicate]

This question already has answers here:
How to count items in comma separated list MySQL
(6 answers)
Closed last year.
I have to do some statics from read-only db where value are stored in a weird form
example:
I have 2 rows like
ID text field
1 1001,1003,1004
2 1003, 1005
I need to be able to count that this is "5".
I don't have write access so don't know how to read and count right away without creation a function or something like that.
Clever solution here on SO: How to count items in comma separated list MySQL
LENGTH(textfield) - LENGTH(REPLACE(textfield, ',', '')) + 1
EDIT
Yes you can select it as an additional column: and correcting with the CHAR_LENGTH from #HamletHakobyan's answer:
SELECT
ID,
textfield,
(CHAR_LENGTH(textfield) - CHAR_LENGTH(REPLACE(textfield, ',', '')) + 1) as total
FROM table
SELECT SUM(LENGTH(textfield) - LENGTH(REPLACE(textfield, ',', '')) + 1)
FROM tablename
There is a small but significant omission in all answers. All will work only if database character set is utf8 or so, i.e. where symbol , gets one byte. The fact that the LENGTH function returns number of bytes instead of chars. Right answer is to use CHAR_LENGTH which returns number of characters.
SELECT
SUM(CHAR_LENGTH(textfield) - CHAR_LENGTH(REPLACE(textfield, ',', '')) + 1) cnt
FROM yourTable
You could use something like this:
select sum(total) TotalWords
from
(
select length(`text field`) - length(replace(`text field`, ',', '')) + 1 total
from yourtable
) x
See SQL Fiddle with Demo
SELECT (LENGTH(column_name) - LENGTH(REPLACE(column_name, ',', '')) + 1) as value_count
FROM table_name
Here LENGTH(column_name) - LENGTH(REPLACE(column_name, ',', '')) gives the number of commas in the value of each column. And +1 with this value provides the number of values separated by comma.
All is wrong and doesn't works for me.
The only one that work is this bellow
SELECT (length(`textfield`) - length(replace(`textfield`, ',', '')) + 1) as my
FROM yourtable;
This is my fiddle
http://sqlfiddle.com/#!9/d5a8e1/10
If someone looking for a solution to return 0 for empty fields.
IF(LENGTH(column_name) > 0, LENGTH(column_name) - LENGTH(REPLACE(column_name, ',', '')) + 1, 0)