I have a table as the following
name
-----------
1@apple@1
2@apple@2
3@apple@4
4@box@4
5@box@5
and I want to get the result as:
name
--------------
apple 3
box 2
Thanks in advance for your help
I have a table as the following
name
-----------
1@apple@1
2@apple@2
3@apple@4
4@box@4
5@box@5
and I want to get the result as:
name
--------------
apple 3
box 2
Thanks in advance for your help
This is what you need.
select
SUBSTRING(
name,
CHARINDEX('@', name) + 1,
LEN(name) - (
CHARINDEX('@', REVERSE(name)) + CHARINDEX('@', name)
)
),
count(1)
from
tbl
group by
SUBSTRING(
name,
CHARINDEX('@', name) + 1,
LEN(name) - (
CHARINDEX('@', REVERSE(name)) + CHARINDEX('@', name)
)
)
use case when
select case when name like '%apple%' then 'apple'
when name like '%box%' then 'box' end item_name,
count(*)
group by cas when name like '%apple%' then 'apple'
when name like '%box%' then 'box' end
If your data does not contain any full stops (or periods depending on your vernacular), and the length of your string is less than 128 characters, then you can use PARSENAME
to effectively split your string into parts, and extract the 2nd part:
DECLARE @T TABLE (Val VARCHAR(20));
INSERT @T (Val)
VALUES ('1@apple@1'), ('2@apple@2'), ('3@apple@4'),
('4@box@4'), ('5@box@5');
SELECT Val = PARSENAME(REPLACE(t.Val, '@', '.'), 2),
[Count] = COUNT(*)
FROM @T AS t
GROUP BY PARSENAME(REPLACE(t.Val, '@', '.'), 2);
Otherwise you will need to use CHARINDEX
to find the first and last occurrence of @
within your string (REVERSE
is also needed to get the last position), then use SUBSTRING
to extract the text between these positions:
DECLARE @T TABLE (Val VARCHAR(20));
INSERT @T (Val)
VALUES ('1@apple@1'), ('2@apple@2'), ('3@apple@4'),
('4@box@4'), ('5@box@5');
SELECT Val = SUBSTRING(t.Val, x.FirstPosition + 1, x.LastPosition - x.FirstPosition),
[Count] = COUNT(*)
FROM @T AS t
CROSS APPLY
( SELECT CHARINDEX('@', t.Val) ,
LEN(t.Val) - CHARINDEX('@', REVERSE(t.Val))
) AS x (FirstPosition, LastPosition)
GROUP BY SUBSTRING(t.Val, x.FirstPosition + 1, x.LastPosition - x.FirstPosition);
No DBMS specified, so here is a postgres
variant. The query does use regexp
s to simplify things a bit.
with t0 as (
select '1@apple@1' as value
union all select '2@apple@2'
union all select '3@apple@4'
union all select '4@box@4'
union all select '5@box@5'
),
trimmed as (
select regexp_replace(value,'[0-9]*@(.+?)@[0-9]*','\1') as name
from t0
)
select name, count(*)
from trimmed
group by name
order by name
Update
For Oracle DMBS, the query stays basically the same:
with t0 as ( select '1@apple@1' as value from dual union all select '2@apple@2' from dual union all select '3@apple@4' from dual union all select '4@box@4' from dual union all select '5@box@5' from dual ), trimmed as ( select regexp_replace(value,'[0-9]*@(.+?)@[0-9]*','\1') as name from t0 ) select name, count(*) from trimmed group by name order by name
NAME | COUNT(*) :---- | -------: apple | 3 box | 2
db<>fiddle here
Update
MySQL 8.0
with t0 as ( select '1@apple@1' as value union all select '2@apple@2' union all select '3@apple@4' union all select '4@box@4' union all select '5@box@5' ), trimmed as ( select regexp_replace(value,'[0-9]*@(.+?)@[0-9]*','$1') as name from t0 ) select name, count(*) from trimmed group by name order by name
name | count(*) :---- | -------: apple | 3 box | 2
db<>fiddle here
You can use case
and group by
to do the same.
select new_col , count(new_col)
from
(
select case when col_name like '%apple%' then 'apple'
when col_name like '%box%' then 'box'
else 'others' end new_col
from table_name
)
group by new_col
;