「<>」を除いて、クエリは問題ありません (実際、提案された代替手段よりもわずかに高速である可能性さえあります!)。いくつかの作業が必要なのはインデックスだけです...
CREATE TABLE contact
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,firstname VARCHAR(255) NOT NULL
,lastname VARCHAR(255) NOT NULL
,type ENUM('small','medium','large') NOT NULL
);
INSERT INTO contact VALUES
(NULL,'John','Brown','small'),
(NULL,'Bill','Red','small'),
(NULL,'Paul','Orange','medium'),
(NULL,'Mike','Green','large'),
(NULL,'John','Scarlet','small'),
(NULL,'John','Cyan','medium'),
(NULL,'Fiona','Brown','large'),
(NULL,'John','Brown','small'),
(NULL,'Chris','Copper','medium'),
(NULL,'Steve','Silver','large');
INSERT INTO contact SELECT NULL,x.firstname, y.lastname, z.type FROM contact x, contact y, contact z;
SELECT COUNT(*) FROM contact;
+----------+
| COUNT(*) |
+----------+
| 1010 |
+----------+
1 row in set (0.01 sec)
SELECT c1.id c1_id
, c2.id c2_id
FROM contact c1
JOIN contact c2
ON c1.firstname = c2.firstname
AND c1.lastname = c2.lastname
AND c1.type=c2.type
WHERE c1.id < c2.id;
...
...
| 1006 | 1008 |
+-------+-------+
5634 rows in set (0.16 sec)
それでは、(firstname,lastname,type) にインデックスを追加しましょう...
DROP TABLE IF EXISTS contact;
CREATE TABLE contact
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,firstname VARCHAR(255) NOT NULL
,lastname VARCHAR(255) NOT NULL
,type ENUM('small','medium','large') NOT NULL
,INDEX(firstname,lastname,type)
);
INSERT INTO contact VALUES
(NULL,'John','Brown','small'),
(NULL,'Bill','Red','small'),
(NULL,'Paul','Orange','medium'),
(NULL,'Mike','Green','large'),
(NULL,'John','Scarlet','small'),
(NULL,'John','Cyan','medium'),
(NULL,'Fiona','Brown','large'),
(NULL,'John','Brown','small'),
(NULL,'Chris','Copper','medium'),
(NULL,'Steve','Silver','large');
INSERT INTO contact SELECT NULL,x.firstname, y.lastname, z.type FROM contact x, contact y, contact z;
SELECT c1.id c1_id
, c2.id c2_id
FROM contact c1
JOIN contact c2
ON c1.firstname = c2.firstname
AND c1.lastname = c2.lastname
AND c1.type = c2.type
AND c1.id < c2.id;
| 775 | 776 |
...
| 1006 | 1008 |
+-------+-------+
5634 rows in set (0.05 sec)