使用where子句中的键值对列表选择语句

本文关键字:列表 选择 语句 键值对 where 子句 使用 | 更新日期: 2023-09-27 18:26: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)

使用where子句中的键值对列表选择语句

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

有关使用表值参数的详细信息,请参阅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')

试试这个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 

您可以使用联接:

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;