MYSQL: Можете ли вы получить результаты, которые соответствуют 3 из 4 выражений? - PullRequest
10 голосов
/ 17 апреля 2009

Скажите, что у меня есть такой запрос:

SELECT * FROM my_table WHERE name = "john doe" AND phone = "8183321234" AND email = "johndoe@yahoo.com" AND address = "330 some lane";

Но, скажем, мне нужно только 3 из 4, чтобы соответствовать, я знаю, что могу написать очень длинный запрос с несколькими операционными операциями, но мне было интересно, была ли функция для этого?

Спасибо.

Ответы [ 5 ]

19 голосов
/ 17 апреля 2009
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 = "johndoe@yahoo.com" THEN 1 ELSE 0 END +
  CASE WHEN address = "330 some lane"   THEN 1 ELSE 0 END
  >= 3;

Примечание: скорее всего, индексы не будут эффективно использоваться. С другой стороны, очень вероятно, что в любом случае не будет индексов для таких столбцов.

15 голосов
/ 17 апреля 2009

Святое сверхсложность, Бэтмен.

SELECT * 
FROM my_table 
WHERE (
    (name = "john doe") +
    (phone = "8183321234") +
    (email = "johndoe@yahoo.com") +
    (address = "330 some lane")
) >= 3;
7 голосов
/ 17 апреля 2009

То же самое, используя индексы:

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 = "johndoe@yahoo.com"
                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

См. запись в моем блоге для деталей производительности.

1 голос
/ 17 апреля 2009

Мне нравится конструкция IF:

SELECT * FROM my_table
WHERE
(    IF(name    = 'john doe', 1, 0) +
     IF(phone   = '8183311234', 1, 0) +
     IF(email   = 'johndoe@yahoo.com', 1, 0) +
     IF(address = '330 some lane', 1, 0)
) >= 3
0 голосов
/ 17 апреля 2009

Немного изменив запрос Tomalak, чтобы он использовал индексы, если они присутствуют. Хотя, если в каждом поле нет индекса, в любом случае произойдет полное сканирование таблицы.

SELECT
*, 
(
    IF(name="john doe", 1, 0) +
    IF(phone = "8183321234", 1, 0) +
    IF(email = "johndoe@yahoo.com", 1, 0) +
    IF(address = "330 some lane", 1, 0) 
) as matchCount
FROM my_table 
WHERE 
    name = "john doe" OR 
    phone = "8183321234" OR 
    email = "johndoe@yahoo.com" OR 
    address = "330 some lane"
HAVING matchCount >= 3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...