2015-08-28 71 views
0

即時得到錯誤TSQL:SELECT CASE然後當子查詢:錯誤:子查詢返回多個值

Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression. 

在下面的查詢

select case 
     when serial_number like ('550092%') then 

      (select distinct left(product, 6) from dbo.QS_WIP_Errors2 err 
       where err.SERIAL_NUMBER = serial_number) 
       --err.SERIAL_NUMBER in (SERIAL_NUMBER)) 

     else left(SERIAL_NUMBER,6) 

     end as Identnummer 

from dbo.QS_defects def 
where INSPECT_TIME >= '2015-08-01' and INSPECT_TIME <= '2015-08-10' 

(我也試過在註釋代碼) 我真的不能解釋它,因爲我認爲通過選擇一個不同的值不超過一行可以返回。 我在做什麼錯?

+1

錯誤說明了這一切 - 您試圖從'ca​​se'的'then'項目中投射多個值 - 您可以用'TOP 1'限制選擇,但您應該調查您的數據爲什麼它不像你期望的那樣。 – StuartLC

+0

非常感謝 - Top 1是一個很好的解決方法,我沒有想過。據我瞭解這些表,不可能將相同的SERIAL_NUMBER分配給多個產品。我將其標記爲已解決,因爲問題不在上面的代碼中 – Tobi89

+0

不要在沒有'ORDER BY'的情況下使用'TOP 1' – alroc

回答

0

如果serial_number實際上是每個產品都是唯一的,就像您認爲的那樣,即使Serial_Number是唯一的,您獲得多行的原因是因爲您沒有正確別名。總之您有:

SELECT ( select distinct left(product, 6) 
      from dbo.QS_WIP_Errors2 err 
      where err.SERIAL_NUMBER = serial_number) -- NO ALIAS ON serial_number 
FROM dbo.QS_defects def 

在您的相關子你對第二參考serial_number,這意味着它是不明確它是否指的是外表(def)或所述內表中沒有別名(err )。在名稱衝突的SQL Server的情況下,會認爲你的意思是內部表,所以你基本上有:

WHERE err.serial_number = err.serial_number 

這當然將返回所有行,因爲一切都等於本身。該問題的快速示範開始:

DECLARE @T TABLE (ID INT, Name VARCHAR(20)); 
INSERT @T (ID, Name) VALUES (1, 'Test 1'), (2, 'Test 2'); 

SELECT * 
FROM @T AS T1 
     OUTER APPLY 
     ( SELECT CorrelatedName = Name 
      FROM @T AS T2 
      WHERE T2.ID = ID 
     ) AS T3 
WHERE T1.ID = 1; 

這樣做的輸出顯示這兩個「測試1」和「測試2」作爲相關名稱返回:

ID Name  CorrelatedName 
---------------------------------- 
1 Test 1  Test 1 
1 Test 1  Test 2 

有了正確的別名,你只能得到單行:

DECLARE @T TABLE (ID INT, Name VARCHAR(20)); 
INSERT @T (ID, Name) VALUES (1, 'Test 1'), (2, 'Test 2'); 

SELECT * 
FROM @T AS T1 
     OUTER APPLY 
     ( SELECT CorrelatedName = Name 
      FROM @T AS T2 
      WHERE T2.ID = T1.ID 
     ) AS T3 
WHERE T1.ID = 1; 

ID Name  CorrelatedName 
---------------------------------- 
1 Test 1  Test 1 

因此,最終的查詢也許應該是:

SELECT CASE WHEN def.serial_number LIKE '550092%' THEN 
       ( SELECT LEFT(err.Product, 6) 
        FROM dbo.QS_WIP_Errors2 AS err 
        WHERE err.serial_number = def.serial_number 
       ) 
      ELSE LEFT(def.serial_number, 6) 
     END AS IdentNumber 
FROM dbo.QS_defects AS def 
WHERE def.inspect_time >= '2015-08-01' 
AND  def.inspect_time <= '2015-08-10'; 

這是一個再努力一點,但是當我寫查詢我將有資格一切 ,這種方式是立即清除每列是什麼表,像這樣的錯誤變得更加容易辨認。

1.如果它是一個簡單的選擇從一個表我可能不打擾別名,或限定列引用,但即使如此,我仍然嘗試這樣做,以防萬一我需要添加表在一個以後的日期