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

您可以使用 casegroup 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 变体。查询确实使用 regexps 来简化一些事情。

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

DB Fiddle

更新

对于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