IN子句中的SQL多列

时间:2012-10-23 09:46:29

标签: sql oracle

如果我们需要根据给定列的某些值查询表,我们可以简单地使用IN子句。

但是如果查询需要基于多个列执行,我们就不能使用IN子句(在SO线程中使用grepped。)

从其他SO线程,我们可以使用连接或存在子句等来规避这个问题。但是如果主表和搜索数据都在数据库中,它们都可以工作。

E.g
User table:
firstName, lastName, City

给定一个(firstname,lastName)元组列表,我需要获取城市。

我可以想到以下解决方案。

1

构建一个选择查询,例如

SELECT city from user where (firstName=x and lastName=y) or (firstName=a and lastName=b) or .....

2

将所有firstName,lastName值上载到临时表中,并在“用户”表和新登台表之间执行连接。

有没有解决这个问题的方法,一般来说解决这个问题的首选方法是什么?

6 个答案:

答案 0 :(得分:71)

你可以这样做:

SELECT city FROM user WHERE (firstName, lastName) IN (('a', 'b'), ('c', 'd'));

The sqlfiddle

答案 1 :(得分:5)

通常最终会更容易将数据加载到数据库中,即使只是为了运行快速查询。硬编码数据似乎很快进入,但如果您开始进行更改,很快就会变得很痛苦。

但是,如果要将名称直接编码到查询中,可以采用更简洁的方法:

with names (fname,lname) as (
    values
        ('John','Smith'),
        ('Mary','Jones')
)
select city from user
    inner join names on
        fname=firstName and
        lname=lastName;

这样做的好处是它可以在一定程度上将您的数据从查询中分离出来。

(这是DB2语法;可能需要对系统进行一些调整)。

答案 2 :(得分:4)

在Oracle中,您可以这样做:

SELECT * FROM table1 WHERE (col_a,col_b) IN (SELECT col_x,col_y FROM table2)

答案 3 :(得分:1)

确保在firstname和lastname列上有一个索引,然后选择1.这实际上不会对性能产生太大影响。

编辑:在@Dems关于垃圾邮件计划缓存的评论之后,更好的解决方案可能是在包含连接的Firstname + Lastname值的现有表(或单独的视图)上创建计算列,从而允许您执行诸如

之类的查询
SELECT City 
FROM User 
WHERE Fullname in (@fullnames)

其中@fullnames看起来有点像"'JonDoe', 'JaneDoe'"

答案 4 :(得分:1)

通常,您可以轻松地编写Where-Condition,如下所示:

select * from tab1
where (col1, col2) in (select col1, col2 from tab2)

注意
Oracle忽略其中一个或多个所选列为NULL的行。在这些情况下,您可能希望使用NVL - Funktion将NULL映射到特殊值(不应该在值中):

select * from tab1
where (col1, NVL(col2, '---') in (select col1, NVL(col2, '---') from tab2)

答案 5 :(得分:0)

确定每个查询的名称列表是否不同或重复使用。如果它被重用,它属于数据库。

即使每个查询都是唯一的,但出于性能原因将其加载到临时表(#table语法)可能很有用 - 在这种情况下,您将能够避免重新编译复杂查询。

如果修改了最大名称数,则应使用参数化查询。

但是,如果上述情况都不适用,我会按照您的方法#1中的内容查询查询中的名称。