How to separate value by using comma my SQL? - mysql

My table column has rows like this 1001, 1002, 1003 and so on separated by commas. There may be 1 or more comma separated values in each column. I need the total count of these comma separated values in the table. For example if my table has 2 rows one having 1001, 1002, 1003, 1004 and another with 1001, 1005 the output i should get is 6 i.e. 4+2. Kindly assist

there is no function in mysql to count char occurences. but you can replace every comma with nothing. and then you calculate the difference of lenghts which will give you the number of commas, which is one less than the number of values.
select
( LENGTH(col1) - LENGTH(REPLACE(col1, ',', '')) + 1 )
+ ( LENGTH(col2) - LENGTH(REPLACE(col2, ',', '')) + 1 )
AS valCount
from T;
(didn't test that explicitely but at least something very similar to that will do the job.)
replace()
length()

Try:
SELECT SUM(LEN(ColumnName) - LEN(REPLACE(ColumnName, ',', ''))) FROM TableName

This is one of those tasks that'd be much, much easier in the server-side script accessing your database than the database itself. Assuming you've already assigned the comma-separated strings to an array (where $array[1] is equal to the string from row 1:
$array = array("1001, 1002, 1003, 1004", "1001, 1005"); // assigned from database
foreach($array as $k => $v){
$numbersInString[$k] = count(explode(', ', $v));
}
echo implode(' + ',$numbersInString);
This is possible, with creative solutions (such as that from Raffael1984), in MySQL, but seems to much more easily, and concisely, implemented in PHP.
References:
count().
explode().
implode().
foreach().

Did you try using the count() function? You can specify which rows if you need to.
.row[COUNT(name)]
in your query. What does your table look like? I might be able to help more if I know what it looks like

Related

FIND_IN_SET woth trim function for values

I have a column that contains a string of comma delimited values. I use FIND_IN_SET to query this column and it works fine until there is a space between the value and the ,. I cannot control the input. The only solution I have found that works is by running REPLACE on the column within the FIND_IN_SET function. Unfortunately this will remove all spaces and could return undesired results.
The blow example would return both row in the table as opposed to the first one only.
col1 | col2
carpet , foo, bar | myVal1
abc, 123 , car pet | myVal2
Query
SELECT FIND_IN_SET('carpet', REPLACE(col1, ' ', ''));
Is there a way of limiting this to only trim the space wither side of the ,
You could try replacing ,[ ] or [ ], with just comma:
SELECT
col1,
col2,
FIND_IN_SET('carpet', REPLACE(REPLACE(col1, ', ', ','), ' ,', ',')) AS output
FROM yourTable;
Demo
Note: This answers assumes that there would be at most one leading/trailing space around the commas, and that your actual data itself does not contain commas. If there could arbitrary amount of whitespace, this answer would fail. In that case, what you would really need is regex replacement. MySQL 8+ does support this, but a better bet would be to normalize your data and stop storing CSV data like this.

SQL Like statement with regular expressions

My table contains some columns with ;-separated numbers like this :
1;2;43;22;20;12
and so on. It's also possible there's only 1 number in this column like 110, or 2 numbers like this 110;143
I want to select the rows that contain a certain number in this column. The number is in a variable $search_var.
Let's say I need to search for the number 1 in my column. If I use a select with like statement like so :
"SELECT * FROM Table WHERE ids LIKE '%".$search_var."%'"
I get all results containing '1' and not only '1', so I also get 11, 14, 110, 1999 etc.
I think I need to use some sort of regex-statement but I'm lost here... Who can help ?
You might not need regex for this
Set #YourNUmber := 110;
SELECT *
FROM Table
WHERE ';' + ids + ';' LIKE '%;'+ #yourNumber + ';%'
This guarantees there are always ; surrounding all the numbers.
This is formatted for SQL Server. The variable syntax and wildcards might be different if you are using something else.
EDIT:
Thanks #FĂ©lixGagnon-Grenier for the suggestions. I think either of these two will work. See here for a SQL Fiddle example
SELECT *
FROM T
WHERE concat(';',ids,';') LIKE concat('%;', #YourNumber , ';%');
SELECT *
FROM T
WHERE LOCATE(concat(';', #YourNumber , ';'),concat(';',ids,';'))>0
Try this solution if you're using SQL Server. This searches for the number where adjcent characters are not numbers:
SELECT * FROM Table WHERE ids LIKE '%[^0-9]".$search_var."[^0-9]%'

MySQL - Search CSV in CSV Column

I have a table with a column that has CSV.
TableA:
field_id | matches
---------------------
1 1,2,4,6,8,11,14,56
Now I need to get the field_id that matches a user given csv. So for instance, user string is 1,4,11, then it should return some value may be just true.
1.) Find_in_set does not work. Because it takes only one element and searches that in a SET/CSV column.
2.) Cannot use like concat('%,', user_input , ',%'). Because user input may not be in order.
Any other ideas? I guess this is a very common scenario.
Note: I dont need to search all records. I need to search a specific record. So in the above table, I just need to search one record that has field_id = 1. i.e. (where field_id = 1). (May not matter, but just an info)
Well, this is a good argument for having data in a proper relational form. But, you can try:
select t.*
from t
where (find_in_set($user_input, 1) = 0 or
find_in_set(substring_index(substring_index($user_input, ',', find_in_set($user_input, 1)), ',', -1), matches) > 0) and
(find_in_set($user_input, 2) = 0 or
find_in_set(substring_index(substring_index($user_input, ',', find_in_set($user_input, 2)), ',', -1), matches) > 0) and
. . .
Do this for however many values you might have in the userinput set.
I presume there is no straight solution with MySQL query like Find_In_Set. So I guess I will have to handle this with multiple queries or with Looping.

How to count items in comma separated list MySQL

So my question is pretty simple:
I have a column in SQL which is a comma separated list (ie cats,dogs,cows,) I need to count the number of items in it using only sql (so whatever my function is (lets call it fx for now) would work like this:
SELECT fx(fooCommaDelimColumn) AS listCount FROM table WHERE id=...
I know that that is flawed, but you get the idea (BTW if the value of fooCommaDelimColumn is cats,dogs,cows,, then listCount should return 4...).
That is all.
There is no built-in function that counts occurences of substring in a string, but you can calculate the difference between the original string, and the same string without commas:
LENGTH(fooCommaDelimColumn) - LENGTH(REPLACE(fooCommaDelimColumn, ',', ''))
It was edited multiple times over the course of almost 8 years now (wow!), so for sake of clarity: the query above does not need a + 1, because OPs data has an extra trailing comma.
While indeed, in general case for the string that looks like this: foo,bar,baz the correct expression would be
LENGTH(col) - LENGTH(REPLACE(col, ',', '')) + 1
zerkms' solution works, no doubt about that. But your problem is created by an incorrect database schema, as Steve Wellens pointed out. You should not have more than one value in one column because it breaks the first normal law. Instead, you should make at least two tables. For instance, let's say that you have members who own animals :
table member (member_id, member_name)
table member_animal (member_id, animal_name)
Even better: since many users can have the same type of animal, you should create 3 tables :
table member (member_id, member_name)
table animal (animal_id, animal_name)
table member_animal (member_id, animal_id)
You could populate your tables like this, for instance :
member (1, 'Tomas')
member (2, 'Vincent')
animal (1, 'cat')
animal (2, 'dog')
animal (3, 'turtle')
member_animal (1, 1)
member_animal (1, 3)
member_animal (2, 2)
member_animal (2, 3)
And, to answer your initial question, this is what you would do if you wanted to know how many animals each user has :
SELECT member_id, COUNT(*) AS num_animals
FROM member
INNER JOIN member_animal
USING (member_id)
INNER JOIN animal
USING (animal_id)
GROUP BY member_id;
Following the suggestion from #zerkms.
If you dont know if there is a trailing comma or not, use the TRIM function to remove any trailing commas:
(
LENGTH(TRIM(BOTH ',' FROM fooCommaDelimColumn))
- LENGTH(REPLACE(TRIM(BOTH ',' FROM fooCommaDelimColumn), ',', ''))
+ 1
) as count
Reference: http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_trim
I also agree that a refactoring of the tables is the best option, but if this is not possible now, this snippet can do the work.
This version doesn't support leading or trailing commas, but supports an empty value with a count of 0:
IF(values, LENGTH(values) - LENGTH(REPLACE(values, ',', '')) + 1, 0) AS values_count
The answer is to correct the database schema. It sounds like a many-to-many relationship which requires a junction table. http://en.wikipedia.org/wiki/Junction_table
If we do +1 and if we have an empty column it always comes as 1 to make it 0 we can use IF condition in mySQL.
IF(LENGTH(column_name) > 0, LENGTH(column_name) - LENGTH(REPLACE(column_name, ',', '')) + 1, 0)

MySQL: can I do a for-each on a comma separated field?

I just ran into a problem.
I know these integers, $integers: 3,5,15,20.
I only want to select the rows from this following table where all comma separated INT's from the field NUMBERS are found.
TABLE: number_table
Uid Numbers
------------------------
1 3,5,15 OK, since all of NUMBERS are in $integers
2 5,15,20 OK, since all of NUMBERS are in $integers
3 3,4,5,15 NOT OK, since 4 is not found in $integers
4 2,15,20,25 NOT OK, since 2 and 25 is not found in $integers
Is it possible to do a "for-each" on a comma separated string or another way to do this SELECT?
UPDATE: It sounds like this is not possible. I will leave it here for little while. Just a hint. When searching for something in a comma separated string then MySQL provides the WHEERE something IN (comma separated string). What I What I look for is someway to traverse a comma separated string using MySQL but that might not be possible.
Something like this would do it (pseudocode):
SELECT * FROM number_table WHERE each_commaseparated_substring(Numbers , 'IN (3,5,15,20)')
It should NOT be comma separated fields.
It must be rows in the related table.
I haven't tried this, and it's a bit ugly and quite possibly slow but you can try the following.
3,5,15,20
SELECT * FROM number_table
WHERE Numbers (LIKE '%,3,%' OR LIKE '%3,%') AND Numbers LIKE '%,5,%' AND Numbers LIKE '%,15,%' AND Numbers (LIKE '%,20,%' OR LIKE '%,20%')
You may be able to do something with REGEX. But at the very least you could use a stored procedure.
Updated for correctness
Maybe try with concate code using PHP and the implode() function.
Correct the short answer is no, but despite being non-normal data there are solutions that are ugly so not recommended. Specifically make a split string function and loop through each value with a stored procedure.
Can MySQL split a column?
Mysql string split
You could check that the number of commas is one less than the number of search terms found:
SELECT * FROM number_table
WHERE CHAR_LENGTH(Numbers) - CHAR_LENGTH(REPLACE(Numbers, ',', '')) = -1
+ (FIND_IN_SET( 3, Numbers) > 0)
+ (FIND_IN_SET( 5, Numbers) > 0)
+ (FIND_IN_SET(15, Numbers) > 0)
+ (FIND_IN_SET(20, Numbers) > 0)
To create this from $integers using PHP:
$sql = "SELECT * FROM number_table
WHERE CHAR_LENGTH(Numbers) - CHAR_LENGTH(REPLACE(Numbers, ',', '')) = -1";
foreach ($integers as $i) $sql .= " + (FIND_IN_SET($i, Numbers) > 0)";