2

我有一个类似于这个简化版本的表格:

CREATE TABLE `accounts` (
  `id` int(11) NOT NULL,
  `account_type_id` int(10) NOT NULL,
  `type` varchar(10) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `accounts` VALUES (1,1,'single'),(2,1,'single'),(3,1,'single'),(4,1,'single'),(5,1,'single'),(6,1,'single'),(7,1,'single'),(8,1,'single'),(9,1,'single'),(10,2,'single'),(11,2,'single'),(12,2,'single'),(13,2,'single'),(14,2,'single'),(15,2,'single'),(16,2,'single'),(17,2,'single'),(18,2,'single'),(19,2,'single'),(20,2,'single'),(21,1,'joint'),(22,1,'joint'),(23,1,'joint'),(24,1,'joint'),(25,1,'joint'),(26,1,'joint'),(27,1,'joint'),(28,1,'joint'),(29,1,'joint'),(30,1,'joint'),(31,2,'joint'),(32,2,'joint'),(33,2,'joint'),(34,2,'joint'),(35,2,'joint'),(36,2,'joint'),(37,2,'joint'),(38,2,'joint'),(39,2,'joint'),(40,2,'joint'),(41,3,'single'),(42,3,'single'),(43,3,'single'),(44,3,'single'),(45,3,'single'),(46,3,'single'),(47,3,'single'),(48,3,'single'),(49,3,'single'),(50,3,'single'),(51,3,'single'),(52,3,'single'),(53,3,'single'),(54,3,'single'),(55,3,'single'),(56,3,'single'),(57,3,'single'),(58,3,'single'),(59,3,'single'),(60,3,'single'),(61,3,'joint'),(62,3,'joint'),(63,3,'joint'),(64,3,'joint'),(65,3,'joint'),(66,3,'joint'),(67,3,'joint'),(68,3,'joint'),(69,3,'joint'),(70,3,'joint'),(71,3,'joint'),(72,3,'joint'),(73,3,'joint'),(74,3,'joint'),(75,3,'joint'),(76,3,'joint'),(77,3,'joint'),(78,3,'joint'),(79,3,'joint'),(80,3,'joint');

我想保留:

  • 随机 5x 类型 = 单一,account_type_id = 1 或 2
  • 随机 5x 类型 = 联合,account_type_id = 1 或 2
  • 随机 5x 类型 = 单一,account_type_id = 3
  • 随机 5x 类型 = 联合,account_type_id = 3

我的方法是获取与上述每个匹配的 5 条记录的 id,然后删除其他所有内容。

(SELECT id FROM accounts WHERE account_type_id IN (1, 2) AND `type` = 'single' ORDER BY RAND() LIMIT 5)
  UNION
(SELECT id FROM accounts WHERE account_type_id IN (1, 2) AND `type` = 'joint' ORDER BY RAND() LIMIT 5)
  UNION
(SELECT id FROM accounts WHERE account_type_id = 3 AND `type` = 'single' ORDER BY RAND() LIMIT 5)
  UNION
(SELECT id FROM accounts WHERE account_type_id = 3 AND `type` = 'joint' ORDER BY RAND() LIMIT 5)

这会正确返回每种所需类型的 5 个 id。但是,如果我尝试直接在 a 中使用该结果集,WHERE id NOT IN (...)则会出现错误(我已替换DELETESELECT示例):

SELECT * FROM accounts WHERE id NOT IN(
    (SELECT id FROM accounts WHERE account_type_id IN (1, 2) AND `type` = 'single' ORDER BY RAND() LIMIT 5)
      UNION
    (SELECT id FROM accounts WHERE account_type_id IN (1, 2) AND `type` = 'joint' ORDER BY RAND() LIMIT 5)
      UNION
    (SELECT id FROM accounts WHERE account_type_id = 3 AND `type` = 'single' ORDER BY RAND() LIMIT 5)
      UNION
    (SELECT id FROM accounts WHERE account_type_id = 3 AND `type` = 'joint' ORDER BY RAND() LIMIT 5)
);

Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNION   (SELECT id FROM accounts WHERE account_type_id IN (1, 2) AND `type` = 'j' at line 3

如果我再添加一个中间子查询,如下所示:

SELECT * FROM accounts WHERE id NOT IN(
    SELECT a.id FROM (
        (SELECT id FROM accounts WHERE account_type_id IN (1, 2) AND `type` = 'single' ORDER BY RAND() LIMIT 5)
          UNION
        (SELECT id FROM accounts WHERE account_type_id IN (1, 2) AND `type` = 'joint' ORDER BY RAND() LIMIT 5)
          UNION
        (SELECT id FROM accounts WHERE account_type_id = 3 AND `type` = 'single' ORDER BY RAND() LIMIT 5)
          UNION
        (SELECT id FROM accounts WHERE account_type_id = 3 AND `type` = 'joint' ORDER BY RAND() LIMIT 5)
    ) a
);

我得到了我想要的结果......请有人解释为什么需要额外的查询?

4

1 回答 1

0

如果你说 NOT IN 意味着

id 不在字段集中 (1 ,2,3,4,5 ,...)

在您的查询 NOT IN 中,然后它找到联合查询,没有一组值。

但是如果您进行额外的子查询,它将选择 a.id 已经是一组 ids 值

那么当你说 NOT IN (那些 ids )时,它会返回正确的结果。

你明白我的意思。

于 2013-10-01T18:12:36.143 回答