単一の組み合わせの場合、これは簡単です。
SELECT COUNT(*)
FROM my_table
WHERE n1 = 3 AND n2 = 10 AND n3 = 4
複数の組み合わせでこれを行いたい場合は、それらの(一時的な)テーブルを作成し、そのテーブルをデータと結合できます。次のようになります。
CREATE TEMPORARY TABLE combinations (
id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
n1 INTEGER, n2 INTEGER, n3 INTEGER
);
INSERT INTO combinations (n1, n2, n3) VALUES
(1, 2, NULL), (4, 10, NULL), (1, 2, 3), (3, 10, 4);
SELECT c.n1, c.n2, c.n3, COUNT(t.id) AS num
FROM combinations AS c
LEFT JOIN my_table AS t
ON (c.n1 = t.n1 OR c.n1 IS NULL)
AND (c.n2 = t.n2 OR c.n2 IS NULL)
AND (c.n3 = t.n3 OR c.n3 IS NULL)
GROUP BY c.id;
( SQLize のデモ)
記述されたこのクエリはOR c.n? IS NULL
、MySQL が最適化するほどスマートではない句のためにあまり効率的ではないことに注意してください。すべての組み合わせに同じ数の用語が含まれている場合は、それらを除外できます。これにより、クエリでデータ テーブルのインデックスを利用できるようになります。
Ps。上記のクエリでは、組み合わせ(1, 2, NULL)
が一致しません(35, 1, 2)
。ただし、(NULL, 1, 2)
両方が必要な場合は、組み合わせの表に両方のパターンを含めるだけで簡単に回避できます。
例に示されているよりも多くの列が実際にあり、連続する列の任意のセットで発生するパターンを一致させたい場合は、列を文字列にパックしてLIKE
orREGEXP
クエリを使用する必要があります。たとえば、すべてのデータ列を という名前の列でコンマ区切りの文字列に連結すると、次のdata
ように検索できます。
INSERT INTO combinations (pattern) VALUES
('1,2'), ('4,10'), ('1,2,3'), ('3,10,4'), ('7,8,9');
SELECT c.pattern, COUNT(t.id) AS num
FROM combinations AS c
LEFT JOIN my_table AS t
ON CONCAT(',', t.data, ',') LIKE CONCAT('%,', c.pattern, ',%')
GROUP BY c.id;
( SQLize のデモ)
テーブル内の実際のデータの一部に接頭辞と接尾辞を追加することで、このクエリをいくらか高速化できCONCAT()
ますが、検索するデータが大量にある場合、これは使用できないため、かなり非効率なクエリになります。インデックスの。大規模なデータセットでこの種の部分文字列検索を効率的に行う必要がある場合は、MySQL よりも特定の目的に適したものを使用することをお勧めします。