【问题标题】:Select statement using list of key value pairs in where clause在 where 子句中使用键值对列表选择语句
【发布时间】:2014-10-16 14:59:56
【问题描述】:

我想找到一种使用 Entity 框架执行此操作的方法,但我会接受 sql 来执行此操作。给定一个键值对列表,有没有办法从 table.colA = item.key 和 table.colB = item.value 的表中选择所有行?

例如给定下表数据:

colA   colB   colC
------------------
1      3      abc
1      3      def
5      6      abc
5      8      def
9      10     abc
9      3      def

还有以下列表:

[{1, 3}, {5, 6}, {9, 3}]

我得到以下行返回:

colA   colB   colC
------------------
1      3      abc
1      3      def
5      6      abc
9      3      def

所以我需要的结果查询会影响:

select * from tableData
where
(colA = 1 AND colB = 3) OR
(colA = 5 AND colB = 6) OR
(colA = 9 AND colB = 3)

【问题讨论】:

    标签: c# sql sql-server entity-framework


    【解决方案1】:

    最简洁的方法是使用表值参数。
    然后,您可以对表参数和目标表进行内连接以从表中检索行。

    有关使用表值参数的详细信息,请参阅 this MSDN 文章。

    如果您使用的是 2008 之前的 SQL 版本,或者不想使用表值参数,则可以将两个值连接在一起并使用 IN 子句,例如:

    SELECT * FROM MyTable WHERE CAST(ColA  as varchar(10)) + '|' + CAST(ColB as varchar(10)) IN ('1|3', '5|6', '9|3')
    

    【讨论】:

      【解决方案2】:

      试试这个 Sqlfiddle 演示 http://sqlfiddle.com/#!3/ff9728/5

      ;WITH split_names 
           AS (SELECT CONVERT(XML, '<cols><col>' 
                                   + Replace( Replace(split.a.value('.','VARCHAR(100)'), 
                                    '}', 
                                  ''), 
                                          ',', '</col><col>') 
                                   + '</col></cols>') AS xmlname 
               FROM   (SELECT Cast ('<M>' 
                                    + Replace(Replace(Replace( Replace( 
                                    '[{1, 3}, {5, 6}, {9, 3}]', ']' 
                                        , ''), 
                                                '[', '' 
                                ), '{', ''), '},', '</M><M>') 
                                + '</M>' AS XML) AS Data) AS A 
                      CROSS apply data.nodes ('/M') AS Split(a)) 
      SELECT colA,colB,colC 
      FROM   <tablename> t 
             JOIN (SELECT xmlname.value('/cols[1]/col[1]', 'int') AS col1, 
                          xmlname.value('/cols[1]/col[2]', 'int') AS col2 
                   FROM   split_names) a 
               ON t.cola = a.col1 
                  AND t.colb = a.col2 
      

      【讨论】:

        【解决方案3】:

        您可以使用连接:

        var input = new List<KeyValuePair<int, int>>
        {
            new KeyValuePair<int, int>(1, 3),
            new KeyValuePair<int, int>(5, 6),
            new KeyValuePair<int, int>(9, 3)
        };
        
        var results = from s in db.Source
                      join i in input on new { s.colA, s.colB } equals new { colA = i.Key, colB = i.Value }
                      select new { s.colA, s.colB, s.colC };
        

        或者您可以使用Contains() 来做到这一点:(切换到Tuple 而不是KeyValuePair,只是为了好玩!)

        var input = new List<Tuple<int, int>>
        {
            new Tuple<int, int>(1, 3),
            new Tuple<int, int>(5, 6),
            new Tuple<int, int>(9, 3)
        };
        
        var results = from s in source
                      where input.Contains(new Tuple<int, int>(s.colA, s.colB))
                      select s;
        

        如果您因实体框架而苦苦挣扎,那么这可能会代替您完成这项工作。它将键值对转换为单个字符串,由任意字符分隔(在本例中为:):

        var input = new List<KeyValuePair<int, int>>
        {
            new KeyValuePair<int, int>(1, 3),
            new KeyValuePair<int, int>(5, 6),
            new KeyValuePair<int, int>(9, 3)
        };
        
        //Combine the two values to be searched into a single one
        var parsedInput = input.Select(i => i.Key + ":" + i.Value);
        
        var results = from s in source
                      where parsedInput.Contains(s.colA + ":" + s.colB)
                      select s;             
        

        【讨论】:

        • 对于第一个我得到:{“无法创建类型为 'System.Collections.Generic.KeyValuePair`2[[System.Int32, mscorlib, Version=4.0.0.0, Culture =neutral, PublicKeyToken=b77a5c561934e089],[System.Single, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'。在此上下文中仅支持原始类型或枚举类型。"}
        • 我得到了第二个类似的结果。
        猜你喜欢
        • 2015-07-25
        • 2018-09-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-20
        • 2013-08-04
        • 2012-07-13
        相关资源
        最近更新 更多