この簡略版に似たテーブルがあります。
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 を正しく返します。ただし、その結果セットを直接使用しようとすると、エラーが発生します (例でWHERE id NOT IN (...)
は に置き換えました)。DELETE
SELECT
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
);
必要な結果が得られました...追加のクエリが必要な理由を誰か説明してください。