MYSQL: Можете ли вы вывести результаты, которые соответствуют 3 из 4 выражений?
Скажем, у меня есть такой запрос:
SELECT * FROM my_table WHERE name = "john doe" AND phone = "8183321234" AND email = "[email protected]" AND address = "330 some lane";
Но скажу, что мне нужно только 3 из 4, чтобы соответствовать, я знаю, что могу написать очень длинный запрос с несколькими OR, но мне было интересно, есть ли для этого функция?
Спасибо.
Ответы
Ответ 1
SELECT
*
FROM
my_table
WHERE
CASE WHEN name = "john doe" THEN 1 ELSE 0 END +
CASE WHEN phone = "8183321234" THEN 1 ELSE 0 END +
CASE WHEN email = "[email protected]" THEN 1 ELSE 0 END +
CASE WHEN address = "330 some lane" THEN 1 ELSE 0 END
>= 3;
Боковое примечание: это, скорее всего, не будет эффективно использовать индексы. С другой стороны, в любом случае столбцы этих столбцов не будут иметь никаких индексов.
Ответ 2
Святая чрезмерная сложность, Бэтмен.
SELECT *
FROM my_table
WHERE (
(name = "john doe") +
(phone = "8183321234") +
(email = "[email protected]") +
(address = "330 some lane")
) >= 3;
Ответ 3
То же самое с использованием индексов:
SELECT *
FROM (
SELECT id
FROM (
SELECT id
FROM mytable _name
WHERE name = 'john doe'
UNION ALL
SELECT id
FROM mytable _name
WHERE phone = '8183321234'
UNION ALL
SELECT id
FROM mytable _name
WHERE email = "[email protected]"
UNION ALL
SELECT id
FROM mytable _name
WHERE address = '330 some lane'
) q
GROUP BY
id
HAVING
COUNT(*) >= 3
) di, mytable t
WHERE t.id = di.id
Подробнее о деталях производительности см. запись в моем блоге.
Ответ 4
Мне нравится конструкция IF:
SELECT * FROM my_table
WHERE
( IF(name = 'john doe', 1, 0) +
IF(phone = '8183311234', 1, 0) +
IF(email = '[email protected]', 1, 0) +
IF(address = '330 some lane', 1, 0)
) >= 3
Ответ 5
Модифицировать запрос Tomalak немного, чтобы он использовал индексы, если они присутствуют. Хотя, если в каждом поле нет индекса, в любом случае произойдет полное сканирование таблицы.
SELECT
*,
(
IF(name="john doe", 1, 0) +
IF(phone = "8183321234", 1, 0) +
IF(email = "[email protected]", 1, 0) +
IF(address = "330 some lane", 1, 0)
) as matchCount
FROM my_table
WHERE
name = "john doe" OR
phone = "8183321234" OR
email = "[email protected]" OR
address = "330 some lane"
HAVING matchCount >= 3