現在のクエリの表現方法とパラメーターの動的リストの入力は、メモリ内でクエリを大幅に構築して実行していることを意味します。その場合、構築するクライアント言語を使用するのがおそらく最善です。とにかく必要なときに要素をドロップするクエリ。私が知っているどの方言でも、SQL パラメーターまたは変数を介してリストを直接挿入することはできません。
つまり、これをコンパイルする方法でより一定のクエリ構造を使用したい場合は、INT Identity(1,1) として宣言された CategoryBdocID フィールドを持つ CategoryBdocs テーブルがあると仮定すると、実行することにより、現在のクエリの行
select *
from library
where libraryID in
(select distinct libraryID from categoryAdocs where categoryAdocID in (4))
or LibraryID in
(select distinct libraryID from categoryBdocs where categoryBdocID in (-1))
-1 - の後にカテゴリ B リストを連結すると、常に何も返されないので安全です。年がリストとして入っていない場合は、次のようなものを使用してオプションのパラメーターとして機能させることができます
or Year in (COALESCE(2004, Year))
そして、2004 の代わりに NULL が出てくると、それ自体と一致して戻ります。ただし、リストを使用してそれを行うことはできません。オプションのリストを使用して SQL でそれを行うクリーンな方法は考えられません。
これはすべて、メモリ内にクエリを作成して実行しているという前提に基づいていますが、それはあなたがしているように見えるものです。これを行うのは好きではないとおっしゃいましたが、私も同意します。理想的には効率的ではなく、リストを渡してクエリに連結すると、SQL インジェクションにさらされやすくなります。
これを回避するには、これをストアド プロシージャにラップすることをお勧めします。次に、3 つのリストのそれぞれに ID を含む区切り文字列を渡すと、数値/集計テーブルに対して結合することで、それらを個々の値のテーブルに分割できます (詳細は別の私の回答 - SQL select from data in query where this dataまだデータベースにありませんか? )。ここから、次の行に沿って書くことができます
SELECT L.*
FROM Library L
INNER JOIN CategoryADocs A
ON L.LibraryID=A.LibraryID
INNER JOIN ([CategoryA Derived table]) ADocs
ON A.CategoryAdocID=ADocs.CategoryADocID
LEFT JOIN (SELECT B.* FROM CategoryBDocs B
INNER JOIN [CategoryB Derived Table] BDocs
ON B.CategoryBdocID=BDocs.CategoryBDocID) B
ON L.LibraryID=B.LibraryID
LEFT JOIN ([Years Derived table]) Y
ON L.Year=Y.Year
WHERE
COALESCE(B.LibraryID,-1)=CASE WHEN Len(@BIDs) > 1 THEN B.LibraryID ELSE -1
AND COALESCE(L.Year,-1)=CASE WHEN Len(@Years) > 1 THEN L.Year ELSE -1
私が認めているのは、長くて複雑な方法ですが、動的なクエリを構築する必要なく、すべてのロジックを SQL に入れることができます。それが複雑さに見合う価値があると思うかどうかは、あなた次第です!