独特且相加,如果喜欢

时间:2019-07-18 07:35:04

标签: sql sql-server count distinct-values charindex

我有一个如下表

name
-----------
1@apple@1
2@apple@2
3@apple@4
4@box@4
5@box@5

我想得到的结果是:

name
--------------
apple 3
box   2

预先感谢您的帮助

5 个答案:

答案 0 :(得分:2)

这就是您所需要的。

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)
    )
  )

答案 1 :(得分:1)

用例何时

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

答案 2 :(得分:1)

如果您的数据不包含任何句号(或句点,具体取决于您的本地语言),并且字符串的长度小于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来查找字符串中@的第一个和最后一个匹配项(也需要REVERSE才能获得最后一个位置),然后使用{{ 3}}提取这些位置之间的文本:

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);

答案 3 :(得分:1)

未指定DBMS,因此这里是postgres的变体。该查询确实使用regexp来简化操作。

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

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]*','\1') as name
  from t0
)

select name, count(*)
from trimmed
group by name
order by name
NAME  | COUNT(*)
:---- | -------:
apple |        3
box   |        2

db <>提琴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]*','$1') as name
  from t0
)

select name, count(*)
from trimmed
group by name
order by name
name  | count(*)
:---- | -------:
apple |        3
box   |        2

db <>提琴here

答案 4 :(得分:0)

您可以使用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
;