0

エラーが発生します

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'

(コメントのコードも試しました)複数の行を返すことができない個別の値を選択することで思ったので、本当に説明できません。私は何を間違っていますか??

4

1 に答える 1

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

相関サブクエリでは、 への 2 番目の参照にエイリアスがありません。これは、外部テーブル ( )serial_numberを参照するか内部テーブル ( ) を参照するかが曖昧であることを意味します。名前の競合が発生した場合、SQL Server は内部テーブルを意味すると想定するため、基本的には次のようになります。deferr

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;

この出力は、"Test 1" と "Test 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。このようにして、各列がどのテーブルからのものであるかがすぐに明確になり、このようなエラーを見つけやすくなります。

1. 1 つのテーブルから単純に選択する場合は、エイリアスや修飾列参照に煩わされることはありませんが、後でテーブルを追加する必要がある場合に備えて、それでもそうしようとします。

于 2015-08-28T12:32:40.417 に答える