2017-03-06 59 views
1

我需要從SQL表字段的前10個字選擇查詢。從SQL表中選擇前10個字表

我有字段名稱:說明,所以我需要從描述字段的前10個單詞。

EX:描述:我對這個答案不滿意;我不喜歡GROUP BY,我寧願不做數字表。希望有人能接我。

輸出:我對這個答案感覺不好,我不喜歡

+0

請加預期的輸出,輸入和你嘗試過什麼到目前爲止 – TheGameiswar

+0

看這裏瞭解更多關於如何提出完美的問題:https://spaghettidba.com/2015/04/24/how-to-post-at-sql-question-on-a-public-forum/ – TheGameiswar

+0

* What * answers你在說什麼?在任何情況下,數字表格可以讓事情更快*。問題本身就是問題 - 它非常含糊。無論如何,SQL不是一個字符串操作語言。這不是你是否喜歡查詢,而是它是否以最有效的方式產生結果 –

回答

1

您可以檢查this答案,以瞭解如何在SQL Server的上下文中實現和使用.net函數。在這裏,我正在使用SQLSCLR執行.netRegex.Match函數。

DECLARE @DataSource TABLE 
(
    [Description] NVARCHAR(MAX) 
); 

INSERT INTO @DataSource ([Description]) 
VALUES ('word01, word02,   word03, word04, word05, word06') 
     ,('word01,word02, word03, word04, word05, word06') 
     ,('word01!word02, word03: word04, word05, word06'); 

SELECT * 
FROM @DataSource DS 
CROSS APPLY [dbo].[fn_Utils_RegexMatches] ([Description], '^(\w+\b.*?){3}') RM; 

這給你以下的輸出:

enter image description here

這也太詳細(和extraging只有第一個three話)。你最終的查詢可以是這樣的:

SELECT DS.[Description], RM.[CaptureValue] 
FROM @DataSource DS 
CROSS APPLY [dbo].[fn_Utils_RegexMatches] ([Description], '^(?n)(\w+\b.*?){3}') RM; 

enter image description here

總之,使用正則表達式,你可以使用你想要的任何分離器,但更重要的是,你可以在T-SQL上下文中執行.net代碼這是巨大的。

你有很多要閱讀和從這裏學習。以前的答案更容易和更快實施。

+1

巨大的內存消耗和延遲。即使使用最仔細的編碼,正則表達式也會生成匹配樹,無論您是否需要結果。這些查詢被寫入的方式,它將爲* all *行這樣做。有一個原因SQLCLR字符串拆分方法*不*使用正則表達式 –

+0

是的,你是對的。您需要測試每次您的解決方案,以確保它能按照您的生產數據預期的那樣工作。這僅是SQLCLR的演示。 – gotqn

+0

這是一個示範鏈接。如果您搜索'T-SQL string split',您會發現各種SQLCLR實現。最快速地枚舉字符直接只要需要。速度與SQL Server 2016的STRING_SPLIT相當。如果你只需要100個單詞中的10個單詞,這是一個巨大的進步 –

1

left()函數是否正常?

從your_table中選擇left(Description,10);

+2

這將返回前10個字符,而不是前10個字 –

3

另一種選擇是使用CROSS APPLY和一點XML。 CROSS APPLY中的邏輯可以輕鬆移植到UDF(標量或表值)中。

Declare @YourTable table (ID int,LongDesc varchar(max)) 
Insert into @YourTable values 
(1,'I don''t feel good about this answer; I don''t like the GROUP BY and I would rather not do the table of numbers. Hopefully somebody can pick me up on this.') 

Select A.ID 
     ,ShortDesc = B.S 
From @YourTable A 
Cross Apply (
       Select S = xDim.value('/x[1]','varchar(100)')+' ' 
          +xDim.value('/x[2]','varchar(100)')+' ' 
          +xDim.value('/x[3]','varchar(100)')+' ' 
          +xDim.value('/x[4]','varchar(100)')+' ' 
          +xDim.value('/x[5]','varchar(100)')+' ' 
          +xDim.value('/x[6]','varchar(100)')+' ' 
          +xDim.value('/x[7]','varchar(100)')+' ' 
          +xDim.value('/x[8]','varchar(100)')+' ' 
          +xDim.value('/x[9]','varchar(100)')+' ' 
          +xDim.value('/x[10]','varchar(100)') 
       From (Select Cast('<x>' + replace((Select replace(A.LongDesc,' ','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml) as xDim) as A 
      ) B 

返回

ID ShortDesc 
1 I don't feel good about this answer; I don't like 
+0

@maSTArHiAn我都是基準測試,並且在我錯誤時願意承認。但是,在這種情況下,我的方法更快。對100K記錄進行一系列基準測試。每個運行5次。我的方法平均爲161毫秒。你的方法377毫秒。 –

+0

我明白了。有什麼機會向我展示你是如何做到這一點的? – maSTAShuFu

+0

我應該說你使用了什麼工具? – maSTAShuFu

0

與大數據試試這個。

DECLARE @T TABLE(COL1 NVARCHAR(MAX)) 
INSERT INTO @T VALUES 
('I dont feel good about this answer; I dont like the GROUP BY and I would rather not do the table of numbers. Hopefully somebody can pick me up on this.') 

;WITH CTE AS 
(
select col1,substring(col1,1,CHARINDEX(' ',col1))Words 
,substring(col1,CHARINDEX(' ',col1)+1,len(col1))Residue 
, 1 rn from @t 

union ALL 
select col1,substring(Residue,1,CHARINDEX(' ',Residue)) 
,substring(Residue,CHARINDEX(' ',Residue)+1,len(Residue)) 
,rn+1 
from cte 
where len(Words)>0 and rn<10 
) 
SELECT Words FROM cte 
+0

將需要60ms運行 – maSTAShuFu

+0

@maSTArHiAn,我剛剛測試,爲10,000行(這意味着輸出是1,00,000行)平均時間爲6ms.can你扔樣本數據 – KumarHarsh

+0

執行耗時不寫時間。 – maSTAShuFu

0

我知道你已經有一個答案,但我只是想以不同的方式來做。

DECLARE @WORD VARCHAR(8000)= 'I don''t feel good about this answer; I don''t like the GROUP BY and I would rather not do the table of numbers. Hopefully somebody can pick me up on this.' 
DECLARE @LOOP INT = 1 
DECLARE @STR_POS INT = 1 
DECLARE @CI INT 
DECLARE @RES_STR VARCHAR(8000) = '' 

WHILE(@LOOP<=10) 
    BEGIN 
     SELECT @CI = CHARINDEX(' ',@WORD,@STR_POS) 
     SELECT @RES_STR = @RES_STR +' '+ SUBSTRING(@WORD,@STR_POS,(CHARINDEX(' ',@WORD,@STR_POS)[email protected]_POS)) 
     SET @STR_POS = @CI+1 
     SET @[email protected]+1 

    END 
PRINT @RES_STR 
0

這不會給你一個行解決方案,但另一個選項解析出前十個單詞使用類似的技術與較少的代碼,純粹爲了說明..我想這可以轉換爲用戶定義的函數,但我們知道它們表現不佳。它可能可以使用CrossApply進行組合以消除對UDF的需求。我必須以XML語法貸記本求救:https://www.mssqltips.com/sqlservertip/1771/splitting-delimited-strings-using-xml-in-sql-server/

DECLARE 
@xml as xml, 
@str as varchar(1000)= 'I don''t feel good about this answer; I don''t like the GROUP BY and I would rather not do the table of numbers. Hopefully somebody can pick me up on this.', 
@delimiter as char(1) = char(32), 
@xmlspace as char(13) = '<y>&#160;</y>' 

SET @xml = cast(('<x>'+replace(@str,@delimiter,@xmlspace)+'</x>') as xml) 

SELECT TOP 10 N.value('.', 'varchar(50)') FROM @xml.nodes('x') as T(N) 
+0

這需要43ms才能運行 – maSTAShuFu

0

可以請你試試這個

declare @message nvarchar(max) = 'I don''t feel good about this answer; I don''t like the GROUP BY and I would rather not do the table of numbers. Hopefully somebody can pick me up on this' 

SELECT left(@message, 
CHARINDEX(' ', @message, 
    CHARINDEX(' ', @message, 
    CHARINDEX(' ',@message, 
    CHARINDEX(' ',@message, 
     CHARINDEX(' ',@message, 
     CHARINDEX(' ',@message, 
     CHARINDEX(' ',@message, 
     CHARINDEX(' ',@message, 
      CHARINDEX(' ',@message, 
      CHARINDEX(' ',@message) + 1) + 1) + 1) + 1) + 1) + 1) + 1)+ 1) + 1)) 

問候