特殊选择查询

时间:2012-08-01 04:29:20

标签: c# sql sql-server

我的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 个答案:

答案 0 :(得分:1)

尝试类似:

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

执行查询;

答案 1 :(得分: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

答案 2 :(得分:0)

LINQ的

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 

您可以在how to parametrize your sql query

上获取相关信息

答案 3 :(得分: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查询进行了一些快速测试,并确认您确实可以期望随着所选项目数量的增加,这种方法逐渐变慢。但更糟糕的问题是编译查询所花费的时间。我在一个非常快的服务器上尝试了这个,并且发现当大约一百个交叉连接时,该步骤大约需要8秒。

在产生此错误之前,SQL Fiddle没有让我在任何地方附近做任何事情(并且在此过程中花费的时间超过十秒):查询处理器耗尽了内部资源,无法生成查询计划。这是一种罕见的事件,仅适用于引用大量表或分区的极其复杂的查询或查询。请简化查询。如果您认为自己错误地收到了此消息,请与客户支持服务部​​门联系以获取更多信息。

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

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