2010-10-13 60 views
4

考虑:如何在mssql中获取字符串列的不同字符?

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

想要的结果:

JOSEFKNMLRZWIAU 

(在结果的情况下并不重要 - 它只是更容易保持上键的同时书写)

有什么办法在T-SQL中这样做?


对不起......我混行和列... 它的1列和n行

MLRZWIAU

  • 中号来自Somos
  • 大号来自Knoller来自Knoller
  • ...

更清楚了吗?

+0

嗯,我想我不明白的结果,假设输入的逻辑。 – 2010-10-13 12:57:01

+0

这是3个不同的行,你想要所有3个不同的字符组合? – 2010-10-13 12:57:27

+0

你想达到什么目的? – 2010-10-13 12:57:54

回答

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

谈论大锤打击坚果。那是糟糕的。 – smirkingman 2010-10-13 13:11:50

+3

@smirkingman - 等待你的更好的解决方案:-)。安德烈亚斯 - 那个错误不是来自我的代码。你怎么使用它? – 2010-10-13 13:15:11

+0

您好,马丁,您能解释一下,或者给我一个链接,我可以在那里阅读'''',即CTE中的'信件'。我不明白它是如何工作的。 – Kashif 2010-10-13 18:09:16

3

这是一个相当常见的SQL难题。您需要一个Numbers表格,我将在这里使用CTE(假定SQL Server 2005或更高版本)生成这个表格。

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

完成需要25秒。难道不是很多时间? – Kashif 2010-10-13 13:47:18

+0

@Muhammad:由于我用于生成Numbers表的技巧,它可能取决于你在运行这个数据库的哪个数据库。请尝试将它运行在相对较小的模型中,例如Model,它对我来说运行时间为1秒。我喜欢[Martin的答案]中的技巧(http://stackoverflow.com/questions/3923830/howto-get-distinct-characters-of-string-column-in-mssql/3923947#3923947),用于生成Numbers表恰到好处的大小。 – 2010-10-13 13:51:55

+2

@Joe - 只是做了一些测试,因为我一直想解决这个问题很长一段时间,然后找到[这个答案](http:// stackoverflow。com/questions/10819/sql-auxiliary-table-of-numbers/2663232#2663232)与我也得出的结论一致。即Itzik Ben Gan的cross加入CTE方法是生成非永久性数字表格的最佳方式。它也比我的测试中的永久性表格更快,但是一旦表格被缓存,就会被永久性表格所击败。 – 2010-10-13 18:31:13

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 
相关问题