0

以下に説明するように、3つのテーブルがあります。

dbo.ServiceEntry
ID  RunLogEntry  Reconciled
1    0            1
2    4            1
3    5            1

dbo.ServiceEntryPart
ID  ServiceEntryID  PartId     ServiceEntryTypeID
1    1                3          1
2    2                4          2
3    2                4          1,2

dbo.Part
ID  Desc     Active (bitfield)
3   xyz        1
4   abc        1

次のようにクエリします。

SELECT * 
  FROM ServiceEntry AS S 

 WHERE (S.RunLogEntryID is not null) AND (S.Reconciled=@ReconciledValue) 
   AND EXISTS (SELECT ServiceEntryID 
                 FROM ServiceEntryPart   SEP  
                 JOIN Part on SEP.PartID = Part.ID    
                WHERE ((@ActivePart = 0 AND Part.Active is not null) 
                    OR (@ActivePart = 1 and Part.Active = 0))      
                  AND (@ServiceTypes is null 
                    OR CHARINDEX(','+cast(SEP.ServiceTypeIDs as varchar(255))+',',','+@ServiceTypes+',') > 0))
    OR (NOT EXISTS (SELECT ServiceEntryID 
                      FROM ServiceEntryPart   SEP  
                      JOIN Part on SEP.PartID = Part.ID))

サービス エントリには、0 の runlogentry id を含むレコードがいくつかあります。サービス エントリ テーブルの runlogentryid 値が 0 の場合、そのサービス エントリのサービス エントリ パート レコードはありません。そのため、たとえばクエリが存在する場合と存在しない場合に気付くように、それらを 2 つに分割しました。exists ステートメントは、サービス エントリ部分を持つすべてのサービス エントリを処理し、これらに対してフィルタが適用されます。フィルターに値がある場合、フィルター servicetypeids および activepart はサービス エントリ パーツを持つレコードのみを対象としているため、存在しないブロックは必要ありません。つまり、パラメータが渡されない場合、最初の exists ブロックはサービス パーツを持つサービス エントリをフェッチし、not exists ブロックは runlogentry id が 0 OR NOT null のサービス エントリをフェッチします。これはそのままでうまくいきます。問題は、パラメーターが渡されたときに、サービス エントリ部分を持たないサービス エントリを除外する必要があり、それらが存在する場合に正しい結果が得られないことです。私は問題を説明する良い仕事をしたことを願っています..助けてください

4

3 に答える 3

0

SQLの残りの部分を理解しようとせずに、パラメーターがnullのときにNOT EXISTS句を回避するだけであれば、次のようなことができます。

SELECT * 
  FROM ServiceEntry AS S 
  JOIN     
 WHERE (S.RunLogEntryID is not null) AND (S.Reconciled=@ReconciledValue) 
   AND EXISTS (SELECT ServiceEntryID 
                 FROM ServiceEntryPart   SEP  
                 JOIN Part on SEP.PartID = Part.ID    
                WHERE ((@ActivePart = 0 AND Part.Active is not null) 
                    OR (@ActivePart = 1 and Part.Active = 0))      
                  AND (@ServiceTypes is null 
                    OR CHARINDEX(','+cast(SEP.ServiceTypeIDs as varchar(255))+',',','+@ServiceTypes+',') > 0))
    OR (@ReconciledValue is null and @ActivePart is null and @ServiceTypes is null
        and (NOT EXISTS (SELECT ServiceEntryID 
                      FROM ServiceEntryPart   SEP  
                      JOIN Part on SEP.PartID = Part.ID)))
于 2012-07-25T04:30:22.453 に答える
0

これはおそらくあなたが望むものではありません。正直なところ、クエリはいたるところにあるようです。

'(@ActivePartがnullまたは@ActivePart = Part.Active)'のようなアクティブなパーツフィルターを探している可能性があります。あなたの存在は、内部結合によって暗黙的に処理されます。あなたが探しているものに近いと私が信じる質問は以下の通りです。

select *
FROM ServiceEntry AS S
INNER JOIN ServiceEntryPart AS SEP ON SEP.ServiceEntryID = S.ServiceEntryID
INNER JOIN Part AS P ON P.PartID = SEP.PartID
WHERE S.RunLogEntryID is not null
    and S.Reconciled = @ReconciledValue
    and (@ActivePart is null or @ActivePart = Part.Active)
    and (@ServiceTypes is null or charindex(','+cast(SEP.ServiceTypeIDs as varchar(255))+',',','+@ServiceTypes+',') > 0
于 2012-07-25T04:31:13.503 に答える
0

あなたの列のビジネス定義を持っていないので確信が持てませんが、Part.Active を扱う条件が間違っているのではないかと思います。値は NULL または 0 ではなく、0 または 1 であると予想されます。そのため、パラメーターが NULL の場合、またはパラメーターが列と一致する場合、テストは TRUE を返す必要があると考えるべきです。

CHARINDEX 関数のパラメーターが逆になっています。

操作の正しい順序を取得するには追加の括弧が必要であり、OR NOT EXISTS 句には、パラメーターが NULL の場合にのみ true にするための追加の条件が必要です。

以下は、あなたが探しているものにはるかに近いと思います。しかし、ServiceTypes テストが心配です。パラメータに単一の ServiceTypeID が含まれている場合にのみ、確実に機能します。複数の ID が含まれていると、機能しない場合があります。たとえば、「1,3」というパラメーター値は「1,2,3」のリストと一致するはずですが、一致しません。

SELECT *
  FROM ServiceEntry AS S
 WHERE (S.RunLogEntryID IS NOT NULL)
   AND (S.Reconciled=@ReconciledValue)
   AND( EXISTS(
          SELECT ServiceEntryID
            FROM ServiceEntryPart SEP
            JOIN Part ON SEP.PartID = Part.ID
           WHERE( @ActivePart IS NULL
                  OR @ActivePart = Part.Active
                )
             AND ( @ServiceTypes IS NULL
                   OR CHARINDEX( ','+@ServiceTypes+',',
                                 ','+cast(SEP.ServiceTypeIDs as varchar(255))+','
                               ) > 0
                 )
        )
        OR( @ActivePart IS NULL
            AND @ServiceTypes IS NULL
            AND NOT EXISTS( SELECT ServiceEntryID
                              FROM ServiceEntryPart SEP
                              JOIN Part on SEP.PartID = Part.ID
                          )
          )
      )
于 2012-07-25T11:28:03.927 に答える