2

一部の列が比較され、一部が無視されるテーブルに重複する行セットが存在するかどうかをテストできる T-SQL 関数を作成したいと考えています。

たとえば、次のデータ セットを考えてみましょう。

BomID   PartNumber  ItemNumber  Quantity    UnitID
4164    10004001    10001419        1         33
4169    10004001    103599          1         33
4171    10004001    103601          1         33
4163    10004001    10001329       10         33
4166    10004001    101823          8         33
10794   10012161    10001419        1         33
10799   10012161    103599          1         33
10801   10012161    103601          1         33
10793   10012161    10001329       10         33
10796   10012161    101823          8         33

10004001Bom.f_GetPartsThatHaveAnIdenticalBom(partNumber)が渡されたときに、 10012161が tuple を比較することによって決定される重複レコードを持っていることを効率的に検出できる関数を書きたいと思います。キー フィールドBomIDは無視されます。したがって、この関数は、同一の BOM を持つ部品番号 (存在する場合) の個別のリストを返します。(ItemNumber, Quantity, UnitID)

この操作は、さまざまな手法を使用して手動で行いました。しかし、このルーチンがますます頻繁に必要になっているように思われるので、セットベースで非常に効率的で、LINQ to Entities クエリで他のテーブルと組み合わせられる関数が必要です。

4

3 に答える 3

2

次のクエリは、を使用full outer joinして2つのセットを比較します。一致しないレコードは、いずれかの側でNULL値になります。having句の比較により、これらが除外されます。

SELECT b1.PartNumber, b2.PartNumber AS TargetPartNumber
FROM bom b full outer join
     bom b2
     ON b1.ItemNumber = b2.ItemNumber AND
        b1.Quantity = b2.Quantity and
        b1.UnitID = b2.UnitID and
        b1.PartNumber <> b2.PartNumber
WHERE b1.PartNumber = @PartNumber
GROUP BY b1.PartNumber, b2.PartNumber
having count(*) = count(b1.PartNumber) and
       count(*) = count(b2.PartNumber)

(itemnumber、quantity、unitid、partnumber)にインデックスを付けることで、これをより効率的にすることができる場合があります。

于 2013-01-11T02:35:53.890 に答える
1

ボブスの回答の修正版に基づく完全なソリューションは次のとおりです。

DECLARE @PartNumber AS udt_PartNumber; SET @PartNumber = N'10012163';

SELECT DISTINCT bom2.TargetPartNumber
FROM
    (
    SELECT PartNumber, COUNT(*) AS ItemCount
    FROM Part.BillsOfMaterials
    WHERE PartNumber = @PartNumber
    GROUP BY PartNumber
    ) AS bom1
JOIN
    (
    SELECT b1.PartNumber, b2.PartNumber AS TargetPartNumber, COUNT(*) AS ItemCount
    FROM Part.BillsOfMaterials b1
    RIGHT JOIN Part.BillsOfMaterials b2 ON b1.ItemNumber = b2.ItemNumber
                AND b1.Quantity = b2.Quantity
                AND b1.UnitID = b2.UnitID
                AND b1.PartNumber <> b2.PartNumber
    WHERE b1.PartNumber = @PartNumber
    GROUP BY b1.PartNumber, b2.PartNumber
    ) AS bom2 ON bom1.PartNumber = bom2.PartNumber
                AND bom1.ItemCount = bom2.ItemCount
WHERE bom1.ItemCount = (SELECT COUNT(*) FROM Part.BillsOfMaterials WHERE PartNumber = bom2.TargetPartNumber)
ORDER BY bom2.TargetPartNumber

唯一の違いは、ソース部品番号の BOM に存在しない余分な行がターゲットに含まれている場合に、一致が見つからないことを保証する最後の WHERE 句です。

于 2013-01-11T17:56:53.680 に答える
1

これは、あなたのために働くかもしれないSQLステートメントです。

DECLARE @PartNumber int = 10004001

SELECT DISTINCT bom2.TargetPartNumber
FROM
    (
    SELECT PartNumber, COUNT(*) AS ItemCount
    FROM bom
    WHERE PartNumber = @PartNumber
    GROUP BY PartNumber
    ) AS bom1
JOIN
    (
    SELECT b1.PartNumber, b2.PartNumber AS TargetPartNumber, COUNT(*) AS ItemCount
    FROM bom b1
    JOIN bom b2 ON b1.ItemNumber = b2.ItemNumber
                AND b1.Quantity = b2.Quantity
                AND b1.UnitID = b2.UnitID
                AND b1.PartNumber <> b2.PartNumber
    WHERE b1.PartNumber = @PartNumber
    GROUP BY b1.PartNumber, b2.PartNumber
    ) AS bom2 ON bom1.PartNumber = bom2.PartNumber
                AND bom1.ItemCount = bom2.ItemCount
WHERE bom1.ItemCount = (SELECT COUNT(*) FROM bom WHERE PartNumber = bom2.TargetPartNumber)
ORDER BY bom2.TargetPartNumber

これをストアド プロシージャまたは関数に入れることができます。@PartNumber関数に渡す値を表します。

于 2013-01-11T02:21:07.160 に答える