So my question is p开发者_运维知识库retty 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)
精彩评论