2010-10-13 5 views
4

Étant donné:Comment obtenir des caractères distincts de la colonne de chaîne dans mssql?

| name 
-+--------------------------- 
| Josef Knoller 
| Josef Somos 
| KFZ Wiesauer 

voulait résultat:

JOSEFKNMLRZWIAU 

(cas dans le résultat n'a pas d'importance - il était plus facile maintenant la touche UPPER alors que l'écriture)

Est-il possible de faites-le dans T-SQL?


désolé ... J'ai la colonne mixte et la ligne ... il est 1 colonne et n rangées

MLRZWIAU

  • M vient de Somos
  • L vient de Knoller
  • R vient de Knoller
  • ...

clearer?

+0

Hmm, je pense que je ne comprends pas la logique du résultat en supposant que l'entrée. –

+0

Est-ce 3 lignes différentes et vous voulez les caractères distincts de tous les 3 combinés? –

+0

qu'essayez-vous d'accomplir? –

Répondre

2
DECLARE @result VARCHAR(MAX) 
SET @result = '' 

DECLARE @t TABLE(name VARCHAR(400)) 

INSERT INTO @t 
SELECT 'Josef Knoller' UNION ALL SELECT 'Josef Somos' UNION ALL SELECT 'KFZ Wiesauer' 

;WITH 
L0 AS (SELECT 1 AS c UNION ALL SELECT 1), 
L1 AS (SELECT 1 AS c FROM L0 A CROSS JOIN L0 B), 
L2 AS (SELECT 1 AS c FROM L1 A CROSS JOIN L1 B), 
L3 AS (SELECT 1 AS c FROM L2 A CROSS JOIN L2 B), 
L4 AS (SELECT 1 AS c FROM L3 A CROSS JOIN L3 B), 
Nums AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS i FROM L4), 
FilteredNums AS (SELECT i FROM Nums WHERE i<= 400), 
Letters AS(
SELECT UPPER(SUBSTRING(name,i,1)) AS L, ROW_NUMBER() OVER (ORDER BY name,i) AS RN 
FROM @t 
JOIN FilteredNums ON FilteredNums.i <= LEN(name)) 

SELECT @result = @result + L 
FROM Letters 
GROUP BY L 
ORDER BY MIN(RN) 

SELECT @result 
+1

Parlez d'un marteau pour casser une noix. C'est terrible. – smirkingman

+3

@smirkingman - En attente de votre meilleure solution :-). Andreas - Cette erreur ne vient pas de mon code. Comment l'utilisez-vous? –

+0

Salut Martin, pouvez-vous m'expliquer ou me donner un lien d'où je peux lire la partie après ',' c'est-à-dire 'Lettres' dans CTE. Je ne comprends pas comment cela fonctionne. – Kashif

3

Ceci est un puzzle SQL assez commun. Vous aurez besoin d'une table Numbers, que je vais générer ici en utilisant un CTE (suppose SQL Server 2005 ou supérieur).

declare @Names table (
    name varchar(100) 
) 

insert into @Names 
    (name) 
    select 'Josef Knoller' union all 
    select 'Josef Somos' union all 
    select 'KFZ Wiesauer' 

;With Numbers As (
    Select Row_Number() Over (Order By c1.object_id) As Value 
    From sys.columns As c1 
     Cross Join sys.columns As c2 
) 
Select Distinct '' + case when Substring(nm.name, N.Value, 1)<>' ' then upper(Substring(nm.name, N.Value, 1)) else '' end 
    From Numbers N 
     Cross Join @Names nm 
    Where N.Value <= Len(nm.name) 
    For Xml Path('') 
+0

Il a fallu 25 secondes pour terminer. N'est-ce pas beaucoup de temps? – Kashif

+0

@Muhammad: En raison de ma technique pour générer la table Numbers, cela peut dépendre de la base de données dans laquelle vous exécutez ceci. Essayez de l'exécuter dans quelque chose relativement petit comme Model, qui s'exécute en 1 seconde pour moi. J'aime la technique dans [la réponse de Martin] (http://stackoverflow.com/questions/3923830/howto-get-distinct-characters-of-string-column-in-mssql/3923947#3923947) pour générer une table de nombres de exactement la bonne taille. –

+2

@Joe - J'ai juste fait quelques tests sur ce sujet car je voulais y arriver pendant un bon moment et j'ai trouvé [cette réponse] (http: // stackoverflow.com/questions/10819/sql-auxiliaire-table-des-nombres/2663232 # 2663232) qui est d'accord avec la conclusion que je suis venu aussi. A savoir que la méthode CTE d'Itzik Ben Gan est la meilleure façon de générer une table de nombres non permanente. Il est également plus rapide qu'une table permanente dans mon test avec un cache froid mais battu par la table permanente une fois la table mise en cache. –

1
DECLARE @result VARCHAR(MAX) 
SET @result = '' 

DECLARE @t TABLE(name VARCHAR(400)) 

INSERT INTO @t 
SELECT 'Josef Knoller' UNION ALL SELECT 'Josef Somos' UNION ALL SELECT 'KFZ Wiesauer' 

;with nums(i) as 
(
    select i=1 
    union all 
    select i=i+1 from nums where i < 400 
), 
Letters AS(
SELECT UPPER(SUBSTRING(name,i,1)) AS L, ROW_NUMBER() OVER (ORDER BY name,i) AS RN 
FROM @t JOIN nums ON nums.i <= LEN(name)) 

SELECT @result = @result + L 
FROM Letters 
GROUP BY L 
ORDER BY MIN(RN) 
OPTION (MAXRECURSION 400) 

SELECT @result