2017-02-21 17 views
1

編輯:我試圖編輯的字段,我意識到是nvarchar(max),並且包含TON的垃圾數據,以及我正在嘗試的擴展開始工作是以逗號分隔值的形式發揮作用的......根據我的要求,這是很不可能的。巨大的感謝所有那些幫助!將字符串更改爲最小/最大值以生成中間值

我問之前,知道我只讀到數據庫訪問權限,不能寫入到臨時表......因爲這是一個解決方案,我認爲......

我使用下面的查詢當前:

USE Database 
GO 
DECLARE @dn VARCHAR(13) 
SET @dn = '%15555555555%' 
SELECT switch_extension, line_number, system_configurations.name, system_configurations.description, lines.system_id 
FROM lines, system_configurations 
WHERE lines.system_id=system_configurations.system_id 
AND switch_extension like @dn 
AND lines.status = 1 

SELECT distinct CS.name, CTD.cti_data_value 
FROM cti_source AS CS with (nolock) 
    JOIN cti_source_data AS CTD with (nolock)ON CS.cti_source_id = CTD.cti_source_id 
--WHERE CS.status = 1 
    AND (CTD.cti_data_name = 'Agent_Ext'or CTD.cti_data_name = 'IVR_Ext') 
    AND CTD.cti_data_value LIKE @dn 

的問題是,CTD.cti_data_value可以包含存儲爲字符串,而不是一個新行的單獨的值15551112223範圍,如「15551112222-15551113333」,而不是15551112222,,...

如果我在這個範圍內查詢@dn(除非開始或結束)範圍的末尾),我沒有得到結果(在上面的例子中,如果我搜索了15551112345,即使它存在於「範圍」中也不會有結果)。

有沒有辦法改變這個在這個單個字符串中得到最小/最大值,然後在最小/最大值之間找到一個結果,還是我上了小溪?

回答

0

您需要將CTD.cti_data_value中的值拆分爲範圍的上限和下限。改變這一行的where子句中...

AND CTD.cti_data_value LIKE @dn 

此...

AND @dn BETWEEN 
    CASE WHEN CHARINDEX('-', CTD.cti_data_value) > 0 THEN 
     SUBSTRING(CTD.cti_data_value, 1, CHARINDEX('-', CTD.cti_data_value) - 1) 
    ELSE 
     CTD.cti_data_value 
    END 
    AND 
    CASE WHEN CHARINDEX('-', CTD.cti_data_value) > 0 THEN 
     SUBSTRING(CTD.cti_data_value, CHARINDEX('-', CTD.cti_data_value) + 1, LEN(CTD.cti_data_value) - CHARINDEX('-', CTD.cti_data_value)) 
    ELSE 
     CTD.cti_data_value 
    END 

這將適應具有的值的範圍(例如X-Y)或只是一個奇異值。我必須警告您,比較字符串變量(例如CHAR,VARCHAR等)中的數值可能會導致不可預知的結果。例如,當比較字符串變量中的數值時,「2」大於「10」。

如果您完全確定CTD.cti_data_value中的數字始終是相同的數字位數,您會很好。如果不是的話,你應該轉換數值爲INT(或其他適合您的情況),這樣的...

AND CONVERT(INT, @dn) BETWEEN 
    CONVERT(INT, CASE WHEN CHARINDEX('-', CTD.cti_data_value) > 0 THEN 
     SUBSTRING(CTD.cti_data_value, 1, CHARINDEX('-', CTD.cti_data_value) - 1) 
    ELSE 
     CTD.cti_data_value 
    END) 
    AND 
    CONVERT(INT, CASE WHEN CHARINDEX('-', CTD.cti_data_value) > 0 THEN 
     SUBSTRING(CTD.cti_data_value, CHARINDEX('-', CTD.cti_data_value) + 1, LEN(CTD.cti_data_value) - CHARINDEX('-', CTD.cti_data_value)) 
    ELSE 
     CTD.cti_data_value 
    END) 
+0

數數字會有所不同。它們可以是長度爲8或11個字符的單個條目,或者如果它是一個範圍,它將是17或23(包括' - ')。 我試圖使用第二種解決方案,但它給出了一個錯誤「Error conversion data type varchar to int」(然後我嘗試了bigint,但這也不起作用) –

+0

是否有值中的非數字字符正試圖轉換? – nscheaffer

+0

它有%作爲通配符,但我甚至刪除了這個嘗試。 http://pastebin.com/15d5q9DJ就是這樣的例子,並且返回「Msg 8114,Level 16,State 5,Line 10 將數據類型nvarchar轉換爲bigint時出錯。 –

0

我想你會需要將字符串分割成不同的組件。見Splitting the string in sql server

現在這是一個讀/寫版本,但你正在做類似的事情。然後你的最小值將始終是分界符之前的位,並且你的最大值將總是在後面的位。

第二個選擇是在.net中編寫一個用戶定義的函數,它將接受字符串,執行完整性檢查並返回您正在查找的適當值。如果性能很重要,CLR的使用在這裏實際上可能是件好事。

但是,如果沒有CLR,您需要:

  1. 找到分隔符的位置( - 在這種情況下)
  2. 拿串起來,但不包括分隔符爲分鐘,
  3. 取分隔符後面的字符串作爲最大值。
0

您可以使用CTE而不是表格,並通過拆分它們來計算範圍中的最小值和最大值,並檢查@dn是否在這些值之間。確保@dn被聲明爲BIGINT。 我假設你的值總是BIGINT(你的值超過INT)。

這裏的工作的例子來證明這一點:

DECLARE @dn BIGINT = 15555555555; 
    --SET  @dn   = 15551112223; 

    WITH cti_source_data AS (
     SELECT * 
     FROM (VALUES ('15555555555'), ('15551112222-15551113333')) AS V (cti_data_value) 

    ), CTD AS (
     SELECT *, 
       CASE CHARINDEX('-', cti_data_value) WHEN 0 THEN cti_data_value ELSE SUBSTRING(cti_data_value, 0, CHARINDEX('-', cti_data_value)) END MinValue, 
       SUBSTRING(cti_data_value, CHARINDEX('-', cti_data_value)+1, LEN(cti_data_value)) MaxValue 
     FROM cti_source_data 
    ) 
    SELECT * 
    FROM CTD 
    WHERE @dn BETWEEN MinValue AND MaxValue 

至於你的查詢,你需要用熱膨脹係數計算這些最小值和最大值替換表:

DECLARE @dn BIGINT = 15555555555; 

    SELECT switch_extension, line_number, system_configurations.name, system_configurations.description, lines.system_id 
    FROM lines, system_configurations 
    WHERE lines.system_id=system_configurations.system_id 
    AND switch_extension like '%' + @dn '%' 
    AND lines.status = 1 

    ;WITH CTD AS (
     SELECT *, 
       CASE CHARINDEX('-', cti_data_value) WHEN 0 THEN cti_data_value ELSE SUBSTRING(cti_data_value, 0, CHARINDEX('-', cti_data_value)) END MinValue, 
       SUBSTRING(cti_data_value, CHARINDEX('-', cti_data_value)+1, LEN(cti_data_value)) MaxValue 
     FROM cti_source_data (NOLOCK) 
    ) 
    SELECT distinct CS.name, CTD.cti_data_value 
    FROM cti_source AS CS with (nolock) 
     JOIN ON CS.cti_source_id = CTD.cti_source_id 
    --WHERE CS.status = 1 
     AND (CTD.cti_data_name = 'Agent_Ext'or CTD.cti_data_name = 'IVR_Ext') 
     --AND CTD.cti_data_value LIKE @dn 
     AND @dn BETWEEN CTD.MinValue AND CTD.MaxValue 
相關問題