在具有多个条件的一个查询中选择多行

J. *_*Doe 7 mysql select

我可以使用以下内容选择具有一个条件的多行:

SELECT `Col`, `Col2` FROM `Table` WHERE `Col3` IN (?, ?, ?, ?, ?);
# This selects 5 rows
Run Code Online (Sandbox Code Playgroud)

如果有多个条件(所有整数等于运算),如何做到这一点?

查询需要检查三个条件,所有这三个条件构成了复合主键。

单个查询将选择 10 到 100 行(尽管大多数情况下只有 10 行)——它在性能方面必须很快。这就是为什么使用多个查询不是一个好主意。

CREATE TABLE声明是:

CREATE TABLE `Table Name` (
  `X` smallint(6) unsigned NOT NULL,
  `Y` smallint(6) unsigned NOT NULL,
  `Z` smallint(6) unsigned NOT NULL,
  `Data` varchar(2048) NOT NULL DEFAULT '',
  PRIMARY KEY (`X`,`Y`,`Z`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Run Code Online (Sandbox Code Playgroud)

对于多个查询,可以这样做:

SELECT `One`, `Two` FROM `Table` WHERE `X` = ? AND `Y` = ? AND `Z` = ?;
SELECT `One`, `Two` FROM `Table` WHERE `X` = ? AND `Y` = ? AND `Z` = ?;
SELECT `One`, `Two` FROM `Table` WHERE `X` = ? AND `Y` = ? AND `Z` = ?;
# This selects 3 rows but I don't want to make 3 calls to the database server for that
Run Code Online (Sandbox Code Playgroud)

ype*_*eᵀᴹ 11

您有 2 个基本的语法选项可以在一个查询中执行此操作,还有 2 个选项用于确定是发送查询中的值还是首先将它们加载到表中:

前 2 个选项是等效的,但它们的效率可能会有所不同,具体取决于版本。这种IN与元组(行构造函数)的语法在旧版本中不能最有效地使用索引。在 5.7 中,优化器将两种语法标识为等效(请参阅MySQL 文档:行构造函数表达式优化)。测试!

当您想查询多个参数/三元组时,使用表的另一种选择可能会更好。您还可以索引(临时)表。测试!

因此,基本建议是在您的版本/配置/设置中进行测试,表格的大小与其预测的大小相似,并且具有不同数量的参数。


还有两种可能值得测试的方法:

  • 简单的UNION ALL. 因为我们只想运行多个相同的查询,其中只有参数不同。一个缺点是,如果基本查询很复杂并且您有许多三元组要检查,则查询会变得非常长且看起来很笨拙:

    SELECT t.* FROM my_table AS t
    WHERE ( x = ? AND y = ? AND z = ? ) UNION ALL
    SELECT t.* FROM my_table AS t
    WHERE ( x = ? AND y = ? AND z = ? ) UNION ALL
    ---
    SELECT t.* FROM my_table AS t
    WHERE ( x = ? AND y = ? AND z = ? ) ;
    
    Run Code Online (Sandbox Code Playgroud)
  • UNION ALLJOIN变体中使用派生表(带有)。这可能会使用优化(在 5.5 或 5.6 中添加),可以实现和索引派生表:

    SELECT t.*
    FROM my_table AS t
      JOIN 
          ( SELECT ? AS x, ? AS y, ? AS z  UNION ALL
            SELECT ?, ?, ?  UNION ALL
            ---
            SELECT ?, ?, ?
          )
        AS tmp
      ON  ( t.x = tmp.x AND t.y = tmp.y AND t.z = tmp.z )
     ;
    
    Run Code Online (Sandbox Code Playgroud)