Организация базы данных предложений и ключевых слов
offers
offer_id
offer_name

words
word_id
word_name

matching
matching_id
offer_id
word_id

SELECT
  offer_name,
  matching_count
FROM
  (
    SELECT
      offer_id,
      offer_name,
      COUNT(*) AS matching_count
    FROM
      words
      JOIN matching USING(word_id)
      JOIN offers USING(offer_id)
    WHERE
      word_name = 'KC1'
      OR word_name = 'KC2'
    GROUP BY
      offer_id,offer_name
  ) AS mt
ORDER BY
  matching_count DESC


Если хочется очень быстро — можно сфинксом попробовать
Попробую разжевать.

У вас есть предложение, каждое предложение — это одна запись в таблице offers
набор минимальных полей
offer_id — идентификатор
offer_name — имя

Далее вы можете добавить одно поле words и перечислить из через разделитель. Но в этом случае прийдется искать предложения, учитывая разделители по текстовому полю words. Это уже заведомо не правильно. Следовательно лучше всего сделать еще одну таблицу, в которой слова связаны с предложением words

word_id
offer_id
word_name

Уже лучше и так довольно просто посчитать количество, выборка будет быстрее. Но поле word_name у нас избыточное. То есть мы будем хранить лишнюю информацию (одинаковые слова) Поэтому лучше всего создать две таблицы — список слов (теги) и соответствие предложений и тегов.

words
word_id
word_name

matching
matching_id
offer_id
word_id

Тем самым мы пришли к самому первому варианту. Так понятней почему именно так посоветовали?)