2009-10-21 4 views

Répondre

2

La réponse générique est que vous devez diviser chaque nom en tableau des caractères constitutifs, puis les compter.

Vous ne mentionnez pas le SGBDR que vous utilisez. La réponse varie un peu par le moteur de base de données.

Par exemple, cela fonctionne sur 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 

Mais presque certainement ne fonctionnera pas sur tous les autres moteurs de base de données.

+0

+1 Vous pouvez omettre NAMES de la sous-requête CROSS APPLY – Andomar

+0

J'utilise SQL 2005, ce qui est parfait. Merci! – theaxe

0

Une façon est d'utiliser une table temporaire, et le remplir dans une boucle 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 

Une autre façon est de créer une liste de positions de caractères valides dans une table temporaire, ou comme dans cet exemple, avec une expression de table commune récursive (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) 

Je l'ai testé les échantillons de code contre ce jeu de données:

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') 
Questions connexes