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 应用程序中,我在网格视图中显示了Items表的所有记录,并让用户选择其中的几行,然后如果他按下 EditAll 按钮,另一个网格视图应该填充与这些选定项目相关的文档的文件名,但是不是所有的人,

仅与所有选定项目有关的每个文档

是否有任何查询(sql 或 linq)来选择这些文档?

4

4 回答 4

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 回答
1

取一个字符串并继续添加 itemid 逗号分隔,如 1,2,3 然后编写查询,如

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))

然后在数据库中创建一个函数,如下所示

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 回答
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 回答
0

这是一种方法。我会让你弄清楚你想如何提供项目列表作为参数。而且我还假设 (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 在产生此错误之前并没有让我做任何事情(并且在此过程中花费了十多秒):查询处理器用尽了内部资源并且无法生成查询计划。这是一个罕见的事件,仅适用于极其复杂的查询或引用大量表或分区的查询。请简化查询。如果您认为您错误地收到了此消息,请联系客户支持服务以获取更多信息。

将参数列表传递给 SQL Server 有几种可能的方法。假设您更喜欢动态查询解决方案,我认为这个版本仍然更好,同时还注意到 SQL Server 对in.

有很多方法可以让这些东西爆炸。

于 2012-08-01T05:13:49.347 回答