Пример реализации "влоб" (синтаксис MySQL).
Структура:
CREATE TABLE test ( word0 VARCHAR(255),
word1 VARCHAR(255),
word2 VARCHAR(255),
word3 VARCHAR(255)
);
Запрос:
WITH
cte1 AS (
SELECT *, ROW_NUMBER() OVER () identity
FROM test
),
cte2 AS (
SELECT word0 word, identity FROM cte1 UNION ALL
SELECT word1 word, identity FROM cte1 UNION ALL
SELECT word2 word, identity FROM cte1 UNION ALL
SELECT word3 word, identity FROM cte1
)
SELECT LEAST(t1.word, t2.word), GREATEST(t1.word, t2.word), COUNT(DISTINCT identity)
FROM cte2 t1
JOIN cte2 t2 USING( identity )
WHERE t1.word > t2.word
GROUP BY 1, 2;
DEMO fiddle
Но надо чётко понимать что на заявленных объёмах запрос умрёт навсегда, вместе с сервером.
Для того, чтобы получить хоть сколько-нибудь вменяемое время обработки, надо, во-первых, выполнить нормализацию (преобразование, которое выполняют оба CTE) в статическую проиндексированную таблицу, во-вторых, получать данные не для всего массива сразу, а для достаточно узкого набора слов.