【问题标题】:special select query特殊选择查询
【发布时间】:2012-08-02 11:11:04
【问题描述】:

我的 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 按钮,另一个网格视图应该按文件名填充与这些选定项目相关但不是全部的文档,

仅与 ALL 所选项目相关的每个文档

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

【问题讨论】:

  • @AVD,Tanx 供您回复,但也许您没有仔细阅读我的问题。我知道联接查询,但我想要的不是简单的联接查询。正如我上面所说,我只想要文件与所有选定的项目有关,而不是与一两个或..其中的一个。我希望我能描述我的意图。

标签: c# sql sql-server


【解决方案1】:

尝试类似:

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

并执行查询;

【讨论】:

    【解决方案2】:

    取一个字符串并继续添加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
    

    【讨论】:

    • 嗨,Tanx 为您的答复。我已经测试了您的解决方案,但结果不是我想要的...
    【解决方案3】:

    灵巧

    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获取信息

    【讨论】:

      【解决方案4】:

      这是一种方法。我会让你弄清楚你想如何提供项目列表作为参数。而且我还假设 (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 内的值数量有限制。

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

      【讨论】:

      • 嗨 shawnt00,Tanx 为您的回复。我已经测试了您的解决方案,但结果不是我想要的...
      • M_Mogharrabi 我的查询产生的答案与您接受的答案相同。如果该答案适合您的目的,那么您应该使用。如果您有更具体的反馈,我将不胜感激。
      猜你喜欢
      • 2018-04-18
      • 2014-10-27
      • 2019-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多