Суммирование
OR
и CASE
будет работать, но весьма неэффективно, так как они не используют индексы.
Вам нужно сделать UNION
, чтобы индексы могли использоваться.
Если пользователь вводит name
, phone
, email
и address
в базу данных, и вы хотите проверить все записи, которые соответствуют хотя бы 3
из этих полей, вы вводите:
SELECT i.*
FROM (
SELECT id, COUNT(*)
FROM (
SELECT id
FROM t_info t
WHERE name = 'Eve Chianese'
UNION ALL
SELECT id
FROM t_info t
WHERE phone = '+15558000042'
UNION ALL
SELECT id
FROM t_info t
WHERE email = '42@example.com'
UNION ALL
SELECT id
FROM t_info t
WHERE address = '42 North Lane'
) q
GROUP BY
id
HAVING COUNT(*) >= 3
) dq
JOIN t_info i
ON i.id = dq.id
Это будет использовать индексы для этих полей, и запрос будет быстрым.
См. Эту статью в моем блоге для деталей:
- Соответствие 3 из 4 : как сопоставить запись, которая соответствует как минимум
3
из 4
возможных условий
См. Также вопрос , на котором основана статья.
Если вы хотите иметь список DISTINCT
значений в существующих данных, вы просто заключаете этот запрос в подзапрос:
SELECT i.*
FROM t_info i1
WHERE EXISTS
(
SELECT 1
FROM (
SELECT id
FROM t_info t
WHERE name = i1.name
UNION ALL
SELECT id
FROM t_info t
WHERE phone = i1.phone
UNION ALL
SELECT id
FROM t_info t
WHERE email = i1.email
UNION ALL
SELECT id
FROM t_info t
WHERE address = i1.address
) q
GROUP BY
id
HAVING COUNT(*) >= 3
)
Обратите внимание, что это DISTINCT
не является транзитивным: если A
соответствует B
и B
соответствует C
, это не означает, что A
соответствует C
.