2010-10-13 40 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 
相關問題