distinct 和 sum 如果喜欢
distinct and sum if like
我有一个table如下
name
-----------
1@apple@1
2@apple@2
3@apple@4
4@box@4
5@box@5
我想得到的结果是:
name
--------------
apple 3
box 2
提前感谢您的帮助
用例
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
您可以使用 case
和 group by
来做同样的事情。
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
;
这就是你需要的。
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)
)
)
如果您的数据不包含任何句点(或句点,具体取决于您的语言),并且字符串的长度少于 128 个字符,那么您可以使用 PARSENAME
有效地将字符串分成几部分,并提取第二部分:
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);
否则您将需要使用CHARINDEX
to find the first and last occurrence of @
within your string (REVERSE
is also needed to get the last position), then use SUBSTRING
来提取这些位置之间的文本:
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);
未指定 DBMS,因此这里是 postgres
变体。查询确实使用 regexp
s 来简化一些事情。
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]*','') as name
from t0
)
select name, count(*)
from trimmed
group by name
order by name
更新
对于Oracle DMBS,查询基本保持不变:
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]*','') as name
from t0
)
select name, count(*)
from trimmed
group by name
order by name
NAME | COUNT(*)
:---- | -------:
apple | 3
box | 2
db<>fiddle here
更新
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]*','') as name
from t0
)
select name, count(*)
from trimmed
group by name
order by name
name | count(*)
:---- | -------:
apple | 3
box | 2
db<>fiddle here
我有一个table如下
name
-----------
1@apple@1
2@apple@2
3@apple@4
4@box@4
5@box@5
我想得到的结果是:
name
--------------
apple 3
box 2
提前感谢您的帮助
用例
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
您可以使用 case
和 group by
来做同样的事情。
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
;
这就是你需要的。
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)
)
)
如果您的数据不包含任何句点(或句点,具体取决于您的语言),并且字符串的长度少于 128 个字符,那么您可以使用 PARSENAME
有效地将字符串分成几部分,并提取第二部分:
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);
否则您将需要使用CHARINDEX
to find the first and last occurrence of @
within your string (REVERSE
is also needed to get the last position), then use SUBSTRING
来提取这些位置之间的文本:
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);
未指定 DBMS,因此这里是 postgres
变体。查询确实使用 regexp
s 来简化一些事情。
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]*','') as name
from t0
)
select name, count(*)
from trimmed
group by name
order by name
更新
对于Oracle DMBS,查询基本保持不变:
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]*','') as name from t0 ) select name, count(*) from trimmed group by name order by name
NAME | COUNT(*) :---- | -------: apple | 3 box | 2
db<>fiddle here
更新
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]*','') as name from t0 ) select name, count(*) from trimmed group by name order by name
name | count(*) :---- | -------: apple | 3 box | 2
db<>fiddle here