42

如果我们需要根据给定列的某些值集查询表,我们可以简单地使用 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 值上传到临时表中,并在“用户”表和新临时表之间执行连接。

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

4

6 回答 6

99

你可以这样做:

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

sqlfiddle

于 2012-10-23T09:49:36.287 回答
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 语法;可能需要对您的系统进行一些调整)。

于 2012-10-23T09:58:27.160 回答
4

一般来说,您可以像这样轻松编写 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)

于 2017-02-10T07:23:19.990 回答
4

在 Oracle 中,您可以这样做:

SELECT * FROM table1 WHERE (col_a,col_b) IN (SELECT col_x,col_y FROM table2)
于 2015-10-19T20:15:46.640 回答
2

确保您在 firstname 和 lastname 列上有一个索引并使用 1。这实际上根本不会对性能产生太大影响。

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

SELECT City 
FROM User 
WHERE Fullname in (@fullnames)

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

于 2012-10-23T09:51:26.633 回答
0

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

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

如果名称的最大数量是固定的,则应使用参数化查询。

但是,如果上述情况均不适用,我将按照您的方法#1 那样内联查询中的名称。

于 2012-10-23T09:54:58.733 回答