2017-03-08 33 views
-2

轉換失敗這是我的查詢。我的問題是,如果我只是使用語句和t1.DisplayVersion> = '30.6.4.10006'它返回較小的值,因爲它只是看第一個字符。例如,返回任何版本爲8.23.2500的計算機。將varchar值「30 .6.4.10006」轉換爲數據類型int

select distinct v1.guid 
from vComputer v1 
inner join Inv_AddRemoveProgram t1 on v1.Guid = t1._ResourceGuid 
where t1.DisplayName like 'Cisco WebEx Meeting Center%' 
    and CAST(t1.DisplayVersion AS INT) >= '30.6.4.10006' 
    and t1.installflag = '1' 
    and v1.IsManaged = '1' 
+5

驚訝?該值不是整數... – jarlh

+1

你到底想要轉換成什麼? – Siyual

+1

你使用的是MySQL還是MS SQL Server?不要標記不涉及的產品。 – jarlh

回答

-2

嘗試這種情況:

select distinct v1.guid 
from vComputer v1 
inner join Inv_AddRemoveProgram t1 on v1.Guid = t1._ResourceGuid 
where t1.DisplayName like 'Cisco WebEx Meeting Center%' 
    and CAST(Replace(t1.DisplayVersion,'.','') AS BIGINT) >= 306410006 
    and t1.installflag = '1' 
    and v1.IsManaged = '1' 
+0

30.6.4.10006是不是一個數值,不能轉換爲浮動。 –

+0

現在我收到以下錯誤,「將數據類型varchar轉換爲浮點數時出錯」 – user3009669

+0

答案已更新,請重試 – jfatal

0

在字符串比較,「30」小於「8」,因爲它在相同的位置上的單獨的字符進行比較,並3小於8要執行數字比較,您需要使用分隔符函數將文本解析到單獨的字段中,對齊項目然後進行比較。這不會很簡單,並且不可能在任何顯着數量的行上表現良好。

如果您可以通過比較第二個小數點前面的數字,它會更簡單並且性能更好; 30.6 vs 8.23。這些值可以轉換爲十進制並直接進行比較。

--COMPARE JUST THE FIRST TWO 
DECLARE @t TABLE (VersionNumber VARCHAR(50)); 
DECLARE @test VARCHAR(50) = '8.23.2500'; 
INSERT INTO @t (VersionNumber) 
VALUES ('30.6.4.10006'), 
('1.2.3.4'), 
('100.200.300.400'), 
('1.200.3.4'), 
('100.2.3.4'), 
('8.24.2500'), 
('8.23.2501'), 
('8.23.2499'), 
('8.23'); 

SELECT t.VersionNumber, @test, 
     FirstTwo = TRY_CONVERT(decimal(20,2),LEFT(t.VersionNumber, ISNULL(NULLIF(CHARINDEX('.', t.VersionNumber, CHARINDEX('.', t.VersionNumber) + 1), 0) - 1, 8000))), 
     FirstTwoTest = TRY_CONVERT(decimal(20,2),LEFT(@test, ISNULL(NULLIF(CHARINDEX('.', @test, CHARINDEX('.', @test) + 1), 0) - 1, 8000))) 
FROM @t AS t 
WHERE TRY_CONVERT(decimal(20,2),LEFT(t.VersionNumber, ISNULL(NULLIF(CHARINDEX('.', t.VersionNumber, CHARINDEX('.', t.VersionNumber) + 1), 0) - 1, 8000))) 
> TRY_CONVERT(decimal(20,2),LEFT(@test, ISNULL(NULLIF(CHARINDEX('.', @test, CHARINDEX('.', @test) + 1), 0) - 1, 8000))) 
; 
+0

如果我有空閒時間,可能會比較完整的字符串。 –

+0

謝謝,但我不能逃脫比較前兩個。以前的版本是30.6.0.10050,所以它會將版本和最新版本30.6.4.10006視爲相等。 – user3009669

0

這裏是一個遞歸的CTE版本。我認爲它會工作,因爲它爲有限的測試數據返回了正確的結果。您需要進行更廣泛的測試並找出如何將其納入您的解決方案。

總之,它使用Jeff Moden's splitter函數分割字符串,然後根據序數比較值,使用遞歸cte鑽入新值大於或等於現有值的結果。最後,它從原始來源中選擇新值大於現有值的地方。

隨着我的樣本數據,以下版本回來爲新於2500年8月23日:

30.6.4.10006

100.200.300.400

100.2.3.4

2500年8月24日

8.23.2501

該foll由於版本回來不更新超過2500年8月23日:

1.2.3.4

1.200.3.4

2499年8月23日

8.23

2500年8月23日

IF OBJECT_ID('tempdb..#test') IS NOT NULL 
    DROP TABLE #test; 
GO 

DECLARE @t TABLE (VersionNumber VARCHAR(50)); 
DECLARE @test VARCHAR(50) = '8.23.2500'; 
INSERT INTO @t (VersionNumber) 
VALUES ('30.6.4.10006'), 
('1.2.3.4'), 
('100.200.300.400'), 
('1.200.3.4'), 
('100.2.3.4'), 
('8.24.2500'), 
('8.23.2501'), 
('8.23.2499'), 
('8.23'), 
('8.23.2500'); 

SELECT dsk.ItemNumber, 
     Item = CAST(dsk.Item AS INT) 
INTO #TEST 
FROM Utility.DelimitedSplit8K(@test, '.') AS dsk; 

WITH cte 
AS (SELECT t.VersionNumber, 
      t2.ItemNumber, 
      LeftItem = dsk.Item, 
      RightItem = t2.Item, 
      Diff = dsk.Item - t2.Item 
    FROM @t AS t 
     CROSS APPLY Utility.DelimitedSplit8K(t.VersionNumber, '.') AS dsk 
     INNER JOIN #TEST AS t2 
     ON dsk.ItemNumber = t2.ItemNumber 
     WHERE t2.ItemNumber = 1 
     AND dsk.Item - t2.Item > -1 
     UNION ALL 
     SELECT t.VersionNumber, 
      t2.ItemNumber, 
      LeftItem = dsk.Item, 
      RightItem = t2.Item, 
      Diff = dsk.Item - t2.Item 
    FROM @t AS t 
     CROSS APPLY Utility.DelimitedSplit8K(t.VersionNumber, '.') AS dsk 
     INNER JOIN #TEST AS t2 
     ON dsk.ItemNumber = t2.ItemNumber 
     INNER JOIN cte 
     ON cte.ItemNumber +1 = t2.ItemNumber 
     AND cte.VersionNumber = t.VersionNumber 
     WHERE cte.Diff > -1 
     ) 

     SELECT * FROM @t AS t 
     WHERE t.VersionNumber IN 
     ( 
      SELECT cte.VersionNumber FROM cte 
      WHERE cte.Diff > 0 
     ) 
相關問題