我可以在 SQL 中的字段中选择不同/按字符分组吗?

发布于 2024-08-08 15:29:46 字数 125 浏览 2 评论 0原文

我想运行一个查询,对于给定字段将计算特定字符的实例。

例如,如果我有一个名为“朋友”的表,其中“姓名”字段包含行:爱德华、詹姆斯、迈克。我会得到输出:

A 2, d 2, E 3, 我 1, 等等...

I'd like to run a query which for a given field will count the instances of a particular character.

For example if I had a table called 'Friends' with a 'Names' field containing rows: Edward, James, Mike. I'd get the output:

A 2,
D 2,
E 3,
I 1,
and so on...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

忆伤 2024-08-15 15:29:46

一般的答案是,您需要将每个名称分成一个组成字符表,然后对它们进行计数。

您没有提及您正在使用哪种 RDBMS。答案因数据库引擎而异。

例如,这适用于 SQL 2005+:

DECLARE @friends TABLE (NAMES VARCHAR(30))
DECLARE @maxLen INT

INSERT @friends (NAMES)
SELECT 'Edward'
UNION SELECT 'James'
UNION SELECT 'Mike'

SELECT @maxLen = MAX(LEN(NAMES)) FROM @friends

;WITH numsCte 
AS 
( 
        --dynamic numbers table. If you have a numbers table in your database
        --use that instead, as it will be more efficient.
        SELECT 1 AS n 
        UNION ALL 
        SELECT n+1 FROM numsCte 
        WHERE n < @maxLen
)
,charCTE
AS
( 
        --split the string into a dataset
        SELECT *
        FROM numsCte AS nm
        CROSS APPLY (SELECT NAMES, SUBSTRING(NAMES, n, 1) AS splitChar 
                     FROM @friends
                    ) AS st
        WHERE splitChar > ''
)
SELECT  UPPER(splitChar) AS letter
        ,COUNT(1) AS cnt
FROM charCTE
GROUP BY splitChar
ORDER BY splitChar

但几乎肯定不适用于任何其他数据库引擎。

The generic answer is that you need to split each name into a table of constituent characters, then count those.

You don't mention which RDBMS you're using. The answer varies a bit by database engine.

For example, this will work on SQL 2005+:

DECLARE @friends TABLE (NAMES VARCHAR(30))
DECLARE @maxLen INT

INSERT @friends (NAMES)
SELECT 'Edward'
UNION SELECT 'James'
UNION SELECT 'Mike'

SELECT @maxLen = MAX(LEN(NAMES)) FROM @friends

;WITH numsCte 
AS 
( 
        --dynamic numbers table. If you have a numbers table in your database
        --use that instead, as it will be more efficient.
        SELECT 1 AS n 
        UNION ALL 
        SELECT n+1 FROM numsCte 
        WHERE n < @maxLen
)
,charCTE
AS
( 
        --split the string into a dataset
        SELECT *
        FROM numsCte AS nm
        CROSS APPLY (SELECT NAMES, SUBSTRING(NAMES, n, 1) AS splitChar 
                     FROM @friends
                    ) AS st
        WHERE splitChar > ''
)
SELECT  UPPER(splitChar) AS letter
        ,COUNT(1) AS cnt
FROM charCTE
GROUP BY splitChar
ORDER BY splitChar

But almost certainly won't work on any other database engines.

[浮城] 2024-08-15 15:29:46

一种方法是使用临时表,并在 WHILE 循环中填充它:

declare @letters table (letter varchar(1))
declare @pos int
set @pos = 1
while 1=1
    begin
    insert into @letters
    select substring(name,@pos,1)
    from @names
    where len(name) >= @pos

    if @@rowcount = 0
        break

    set @pos = @pos + 1
    end

select letter, count(*)
from @letters
group by letter

另一种方法是在临时表中创建有效字符位置的列表,或者如本例所示,使用递归公用表表达式 (CTE):

declare @maxLen int
select @maxLen = max(len(name)) from @names
;WITH CharPositions (i) AS  ( 
    select 1
    union all
    select i+1 
    from CharPositions
    where i < @maxLen
)
select substring(n.name,cp.i,1), count(*)
from @names n
inner join CharPositions cp on cp.i <= len(n.name)
group by substring(n.name,cp.i,1)

I已针对此数据集测试了代码示例:

declare @names table (name varchar(max))
insert into @names values ('abc')
insert into @names values ('def')
insert into @names values ('def')
insert into @names values ('g')
insert into @names values ('g')
insert into @names values ('g')

One way is to use a temporary table, and populate it in a WHILE loop:

declare @letters table (letter varchar(1))
declare @pos int
set @pos = 1
while 1=1
    begin
    insert into @letters
    select substring(name,@pos,1)
    from @names
    where len(name) >= @pos

    if @@rowcount = 0
        break

    set @pos = @pos + 1
    end

select letter, count(*)
from @letters
group by letter

Another way is to create a list of valid character positions in a temporary table, or as in this example, with a recursive common table expression (CTE):

declare @maxLen int
select @maxLen = max(len(name)) from @names
;WITH CharPositions (i) AS  ( 
    select 1
    union all
    select i+1 
    from CharPositions
    where i < @maxLen
)
select substring(n.name,cp.i,1), count(*)
from @names n
inner join CharPositions cp on cp.i <= len(n.name)
group by substring(n.name,cp.i,1)

I've tested the code samples against this dataset:

declare @names table (name varchar(max))
insert into @names values ('abc')
insert into @names values ('def')
insert into @names values ('def')
insert into @names values ('g')
insert into @names values ('g')
insert into @names values ('g')
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文