1

次のクエリを変更して、パラメータ化できるようにするにはどうすればよいSparePartNamesですか?

すべての必須スペアパーツが変更されていない、つまり少なくとも1つのパーツが欠落している修理のすべてのIDを返します。

スペアパーツの数は、名前だけでなく将来変更される可能性があることに注意してください。動的SQLでストアドプロシージャを使用せずに可能ですか?そうでない場合、このSPはどのように見えるでしょうか?

編集:私はパラメータとしてリスト/配列を渡す方法を知る必要がないことに注意してください、これはSOで無数の時​​間に尋ねられます。私はすでにSplitテーブル値関数も持っています。クエリを書き直して、必須の部分のリストと結合できるように(または何でも) 、少なくとも1つの部分が欠落しているすべてのレコードを見つけることができるようにするにはどうすればよいか疑問に思っています。それで、?'1264-3212,1254-2975'のリストの代わりにのようなvarchar-parameterを使用することは可能NOT EXISTSですか?そもそもはっきりしていなかったら混乱してすみません。

SELECT  d.idData
FROM    tabData d
INNER JOIN modModel AS m ON d.fiModel = m.idModel 
WHERE  (m.ModelName = 'MT27I') 
AND (d.fiMaxServiceLevel >= 2) 
AND (d.Manufacture_Date < '20120511') 
AND (NOT EXISTS
      (SELECT NULL
        FROM  tabDataDetail AS td 
        INNER JOIN tabSparePart AS sp ON sp.idSparePart = td.fiSparePart
        WHERE (td.fiData = d.idData) 
        AND (sp.SparePartName = '1264-3212'))
    OR (NOT EXISTS
      (SELECT NULL
        FROM  tabDataDetail AS td 
        INNER JOIN tabSparePart AS sp ON sp.idSparePart = td.fiSparePart
        WHERE (td.fiData = d.idData) 
        AND (sp.SparePartName = '1254-2975'))
    )
)

残念ながら、ここでどのように使用できるかわかりませんsp.SparePartName IN/NOT IN(@sparePartNames)

4

3 に答える 3

2

これを行う 1 つの方法は、区切り文字列を分割する関数を作成することです。

CREATE FUNCTION [dbo].[Split] 
(
    @Delimiter char(1), 
    @StringToSplit varchar(512)
)
RETURNS table
AS
RETURN 
(
    WITH Pieces(pieceNumber, startIndex, delimiterIndex) 
    AS 
    (
        SELECT 1, 1, CHARINDEX(@Delimiter, @StringToSplit)
        UNION ALL
        SELECT pieceNumber + 1, delimiterIndex + 1, CHARINDEX(@Delimiter, @StringToSplit, delimiterIndex + 1)
        FROM Pieces
        WHERE delimiterIndex > 0
    )
    SELECT 
        SUBSTRING(@StringToSplit, startIndex, CASE WHEN delimiterIndex > 0 THEN delimiterIndex - startIndex ELSE 512 END) AS Value
    FROM Pieces
)

テーブル変数にスペア パーツ名を入力します。

DECLARE @SpareParts TABLE
(
    SparePartName varchar(50) PRIMARY KEY CLUSTERED
);

INSERT INTO @SpareParts
SELECT Value FROM dbo.Split(',', '1264-3212,1254-2975');

次に、テーブル変数に結合します。

SELECT  d.idData
FROM    tabData d
INNER JOIN modModel AS m ON d.fiModel = m.idModel 
WHERE  (m.ModelName = 'MT27I') 
AND (d.fiMaxServiceLevel >= 2) 
AND (d.Manufacture_Date < '20120511') 
AND EXISTS (
        SELECT 1
        FROM  tabDataDetail AS td 
        INNER JOIN tabSparePart AS sp ON sp.idSparePart = td.fiSparePart
        LEFT JOIN @SpareParts AS s ON s.SparePartName = sp.SparePartName
        WHERE td.fiData = d.idData
            AND s.SparePartName IS NULL
    ) 
于 2012-05-11T10:27:32.497 に答える
1

必須のスペアパーツのテーブルまたはビューがある(またはある)と仮定すると、存在するリストは、SparePartNameのtabDataDetail/tabSparePartペアへの左結合で置き換えることができます。不一致は、を使用して報告されますtd.fiSparePart is null

; with mandatorySpareParts (SparePartName) as (
  select '1264-3212'
  union all
  select '1254-2975'
)
SELECT  d.idData
FROM    tabData d
INNER JOIN modModel AS m ON d.fiModel = m.idModel 
WHERE  (m.ModelName = 'MT27I') 
AND (d.fiMaxServiceLevel >= 2) 
AND (d.Manufacture_Date < '20120511') 
AND exists
(
  SELECT null
    from mandatorySpareParts msp
    left join ( tabDataDetail AS td 
                INNER JOIN tabSparePart AS sp 
                   ON sp.idSparePart = td.fiSparePart 
                  AND td.fiData = d.idData
              )
      ON msp.SparePartName = sp.SparePartName
   WHERE td.fiSparePart is null
)

パーツ名はIDに置き換える必要があります。これにより、左結合が簡素化され、クエリが高速化されます。

編集:where句で誤ってtdのフィルタリングを残し、左結合を無効にしました。現在、それが属するON句にあります。

于 2012-05-11T10:57:28.883 に答える
0

テーブル変数を使用して、それに結合します。

于 2012-05-11T10:27:37.347 に答える