16

假设我有一张桌子,email_phone_notes看起来像这样:

+-----------------------+--------------+------+-----+---------+-------+
| Field                 | Type         | Null | Key | Default | Extra |
+-----------------------+--------------+------+-----+---------+-------+
| email                 | varchar      | NO   | PRI | NULL    |       |
| phone                 | varchar      | NO   | PRI | NULL    |       |
| notes                 | text         | NO   |     | 0       |       |
+-----------------------+--------------+------+-----+---------+-------+

因此,每个电子邮件/电话组合都是唯一的,但您可以拥有多个具有不同电话号码的电子邮件地址,反之亦然。这有点做作,但它反映了我的情况。

我想做这样的查询:

SELECT * FROM email_phone_notes  WHERE email = 'foo@bar.com' AND phone = '555-1212';

但是,我想一次做多对,所以我不必做几个SELECT查询。将这对组合在一起也很重要,因为我不想退回未要求的错误电话/电子邮件组合。

我可以做这样的事情,但是对于几百个值的可能性,查询会很长。

SELECT * FROM email_phone_notes WHERE ( 
  (email='foo@bar.com' && phone='555-1212') || 
  (email='test@test.com' && phone='888-1212') || 
   ...

有没有更优雅的解决方案,或者我应该坚持这个?谢谢!

4

3 回答 3

31

如果你追求优雅的 SQL,你可以使用行构造函数:

SELECT * FROM email_phone_notes WHERE (email, phone) IN (
  ('foo@bar.com'  , '555-1212'),
  ('test@test.com', '888-1212')
  -- etc.
);

但是,这根本不适合索引,并且不建议在任何显着大小的表上使用。相反,您可以用您想要的对实现一个表并将其与您的表连接:

SELECT * FROM email_phone_notes NATURAL JOIN (
  SELECT 'foo@bar.com' AS email, '555-1212' AS phone
UNION ALL
  SELECT 'test@test.com', '888-1212'
-- etc.
) t;

或者预填充一个(临时)表:

CREATE TEMPORARY TABLE foo (PRIMARY KEY (email, phone)) Engine=MEMORY
  SELECT email, phone FROM email_phone_notes WHERE FALSE
;

INSERT INTO foo
  (email, phone)
VALUES
  ('foo@bar.com'  , '555-1212'),
  ('test@test.com', '888-1212')
  -- etc.
;

SELECT * FROM email_phone_notes NATURAL JOIN foo;
于 2012-11-17T00:07:41.190 回答
2

您可以使用这样的行构造函数

SELECT *
FROM email_phone_notes
WHERE (email, phone) IN (
  ('foo@bar.com', '555-1212'),
  ('test@test.com', '888-1212')
)

SQLfiddle 示例

于 2012-11-17T00:10:47.810 回答
0

早在 10 年前就提供了较早的答案。现在是 2020 年,答案似乎已经改变。

简短回答:使用行构造函数语法 - 优化器可能(或可能不)使用索引。

此示例中,优化器能够使用索引,即使行构造函数没有覆盖索引的前缀。

于 2021-03-09T10:38:19.213 回答