Reputation: 533
I need to count how many hash tags (or other text) appearances I have in a table. A hash tag placed in a cell (column), but a cell may contains more than one hash tag. A cell contains up to one hash tag of each type.
Example inspired from that question but need to get differ result.
Lets say I have a table that similar to that:
+----+-----------------------+-------------+--+
| id | Items | timestamp1 | |
+----+-----------------------+-------------+--+
| 1 | #Car #Dog #Fish | 01/01/2018 | |
| 2 | #Dog | 25/01/2018 | |
| 3 | #Fish #Dog | 18/03/2019 | |
| 4 | #Car #Dog #Fish | 23/06/2019 | |
| 5 | #Bird | 17/10/2019 | |
+----+-----------------------+-------------+--+
And I need to count how many times each item (#Car, #Dog, etc..) appear.
I have tried this
SELECT (CASE WHEN items like '%#Dog%' THEN 'Dogs'
WHEN items like '%#Car%' THEN 'Cars'
WHEN items like '%#Fish%' THEN 'Fish'
WHEN items like '%#Bird%' THEN 'Birds'
END) as Item, count(*)
FROM observations
GROUP BY (CASE WHEN items like '%#Dog%' THEN 'Dogs'
WHEN items like '%#Car%' THEN 'Cars'
WHEN items like '%#Fish%' THEN 'Fish'
WHEN items like '%#Bird%' THEN 'Birds'
END);
But this will give the (undesired) result:
+-------+----------+
| Item | count(*) |
+-------+----------+
| Birds | 1 |
| Dogs | 4 |
+-------+----------+
Desired results:
+-------+----------+
| count | Item |
+-------+----------+
| 4 | #Dog |
| 2 | #Car |
| 3 | #Fish |
| 1 | #Bird |
+-------+----------+
Is any good way to achieve that?
Upvotes: 1
Views: 69
Reputation: 164099
If the items are known then use UNION ALL to get a query that returns them and then join to the table:
SELECT t.Item, COUNT(o.id) counter
FROM (
SELECT '#Car' AS Item UNION ALL SELECT '#Dog' UNION ALL
SELECT '#Fish' UNION ALL SELECT '#Bird'
) AS t LEFT JOIN observations o
ON CONCAT(' ', o.Items, ' ') LIKE CONCAT('% ', t.Item, ' %')
GROUP BY t.Item;
See the demo.
Results:
| Item | counter |
| ----- | ------- |
| #Car | 2 |
| #Dog | 4 |
| #Fish | 3 |
| #Bird | 1 |
Upvotes: 3
Reputation: 33945
I'm not seriously advocating this as a solution because the correct approach is to fix your data model. However, if this is a one-off problem, for a small data set...
I have a table of integers - ints(i) [0-9]
, but if using MySQL 8.0+, you can emulate this behaviour without the need for the utility table...
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id SERIAL PRIMARY KEY
,items VARCHAR(120) NOT NULL
);
INSERT INTO my_table VALUES
(1,'#Car #Dog #Fish'),
(2,'#Dog'),
(3,'#Fish #Dog'),
(4,'#Car #Dog #Fish'),
(5,'#Bird');
SELECT n
, COUNT(*) total
FROM
( SELECT DISTINCT id
, TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(items,'#',i+1),'#',-1))n
FROM my_table
, ints
WHERE TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(items,'#',i+1),'#',-1)) <> ''
) a
GROUP
BY n;
+------+-------+
| n | total |
+------+-------+
| Bird | 1 |
| Car | 2 |
| Dog | 4 |
| Fish | 3 |
+------+-------+
This assumes that a keyword only appears once per id or, at least, only wants to be counted once per id.
Upvotes: 1