1

SQL データベースに次のような 3 つのテーブルがあります。

Documents : (DocID, FileName) //list of all docs that were attached to items
Items : (ItemID, ...) //list of all items
DocumentRelation : (DocID, ItemID) //the relation between docs and items

私のwinformアプリケーションでは、アイテムテーブルのすべてのレコードをグリッドビューに表示し、ユーザーがそのいくつかの行を選択できるようにし、[すべて編集]ボタンを押すと、別のグリッドビューがこれらの選択されたアイテムに関連するドキュメントのファイル名で埋められるはずですが、それらのすべてではありませんが、

選択したすべてのアイテムに関連する各ドキュメントのみ

これらのドキュメントを選択するためのクエリ ( sql または linq ) はありますか?

4

4 に答える 4

1

1 つの文字列を取り、1,2,3 のようにカンマで区切られた itemid を追加し続け、次のようにクエリを記述します。

declare ItemID varchar(50);
set ItemID='1,2,3';

select FileName 
from documents 
Left Join DocumentRelation on Documents.DocId = DocumentRelation.DocId 
where 
    DocumentRelation.ItemID in (select * from > dbo.SplitString(ItemID))

次に、以下のようにデータベースで1つの関数を作成します

ALTER FUNCTION [dbo].[SplitString] (@OrderList varchar(1000))
RETURNS @ParsedList table (OrderID varchar(1000) ) 
AS BEGIN 
    IF @OrderList = ''  
    BEGIN       
        set @OrderList='Null' 
    end     

    DECLARE @OrderID varchar(1000), @Pos int

    SET @OrderList = LTRIM(RTRIM(@OrderList))+ ','  
    SET @Pos = CHARINDEX(',', @OrderList, 1)

    IF REPLACE(@OrderList, ',', '') <''     
    BEGIN       
        WHILE @Pos 0
        BEGIN
           SET @OrderID = LTRIM(RTRIM(LEFT(@OrderList, @Pos - 1)))

           IF @OrderID < '' 
           BEGIN
               INSERT INTO @ParsedList (OrderID) 
               VALUES (CAST(@OrderID AS varchar(1000))) 
               --Use Appropriate conversion             
           END

           SET @OrderList = RIGHT(@OrderList, LEN(@OrderList) - @Pos)
           SET @Pos = CHARINDEX(',', @OrderList, 1)
        END     
    END     

    RETURN 
END
于 2012-08-01T05:33:17.160 に答える
1

次のようなものを試してください:

string query;
foreach (Item in SelectedItems)
{
   query += "select DocID from DocumentRelation where ItemID =" + Item.Id;
   query += "INTERSECT";
}
query -= "INTERSECT";

そしてクエリを実行します。

于 2012-08-01T04:57:07.773 に答える
0

これが1つのアプローチです。アイテムのリストを引数としてどのように提供するかを考えてみましょう。また、(DocID、ItemID)がリレーションテーブルの主キーであると想定しています。条件は、having選択したすべてのアイテムが探しているドキュメントのリストに関連しているという要件を強制するものです。

;with ItemsSelected as (
    select i.ItemID
    from Items as i
    where i.ItemID in (<list of selected ItemIDs>)
)
select dr.DocID
from DocumentRelation as dr
where dr.ItemID in (select ItemID from ItemsSelected)
group by dr.DocID
having count(dr.ItemID) = (select count(*) from ItemsSelected);

編集

私が知る限り、以下のOPのコメントにもかかわらず、受け入れられた答えはここでの解決策と同等です。

非常に長い一連のintersectクエリを使用していくつかの簡単なテストを行い、選択したアイテムの数が増えると、アプローチが徐々に遅くなることが実際に予想できることを確認しました。しかし、はるかに悪い問題は、クエリをコンパイルするためだけにかかる時間でした。非常に高速なサーバーでこれを試したところ、約100の交差が連結されたときに、そのステップに約8秒かかることがわかりました。

SQL Fiddleは、このエラーを生成する前に(そしてプロセスで10秒以上かかる)私にほとんど何もさせませんでした:クエリプロセッサは内部リソースを使い果たし、クエリプランを生成できませんでした。これはまれなイベントであり、非常に複雑なクエリまたは非常に多数のテーブルまたはパーティションを参照するクエリでのみ発生します。クエリを単純化してください。このメッセージを誤って受信したと思われる場合は、カスタマーサポートサービスに詳細をお問い合わせください。

引数のリストをSQLServerに渡す方法はいくつかあります。動的クエリソリューションを好むと仮定すると、このバージョンの方が優れていると思いますが、内の値の数にはSQLServerの制限があることにも注意してくださいin

このようなものを爆破させる方法はたくさんあります。

于 2012-08-01T05:13:49.347 に答える
0

リンク

var td =
from s in Items
join r in DocumentRelation on s.ItemID equals r.ItemID
join k in Documents on k.DocID equals r.DocID
where Coll.Contains (s.ItemID)         //Here Coll is the collection of ItemID   which you can store when the users click on the grid view row
select new 
{
 FileName=k.FileName,
 DocumentID= k.DocId
 }; 

td コレクションをループして、グリッド ビューにバインドできます

SQL

ストアド プロシージャを作成して、グリッド ビューから選択した itemID に関連するドキュメントを取得し、in 句をパラメータ化します

 select k.FileName,k.DocId from Items as s inner join 
 DocumentRelation as r on 
 s.ItemID=r.ItemID and r.ItemId in (pass the above coll containing selected ItemIds as an input the SP)
 inner join Documents as k
 on  k.DocId=r.DocIk 

SQLクエリをパラメータ化する方法に関する情報を取得できます

于 2012-08-01T04:55:24.420 に答える