За последние 24 часа нас посетили 22714 программистов и 1216 роботов. Сейчас ищут 795 программистов ...

Как вывести наилучшее сопадение из трех баз?

Тема в разделе "MySQL", создана пользователем myks92, 15 ноя 2019.

Метки:
  1. myks92

    myks92 Новичок

    С нами с:
    12 июн 2018
    Сообщения:
    45
    Симпатии:
    1
    Есть три таблицы:

    group_listeners
    - fio
    group_contacts
    - fio
    group_company
    - name

    Мне нужно, сделать поиск-подсказчик. Искать текст по трем таблицам group_listeners.fio,
    group_contacts.fio и group_company.name затем всё это выводить в одно поле name. Я сделал это так:
    PHP:
    1. $search = mb_strtolower($request->post('text'));
    2.  
    3.         return Company::find()
    4.             ->alias('gc')
    5.             ->select([
    6.                 'gc.id as client_id',
    7.                 'TRIM(CONCAT_WS(\' \', gc.name, gl.fio, gct.fio)) as name',
    8.             ])
    9.             ->innerJoin('group_listeners as gl', 'gl.client_id = gc.id')
    10.             ->innerJoin('group_contacts as gct', 'gct.client_id = gc.id')
    11.             ->distinct('gc.name, gl.fio')
    12.             ->orWhere(['like', 'gc.name', $search])
    13.             ->orWhere(['like', 'gl.fio', $search])
    14.             ->orWhere(['like', 'gct.fio', $search])
    15.             ->asArray()
    16.             ->all();
    Однако теперь все три поля выводятся в одно. Но мне нужно как-то Мне нужно сделать так, чтобы наилучшее совпадение попадалось в name.

    есть карточка в ней Иванов А.А. указан в 3х местах с id (к примеру 1000)
    и есть карточка где Иванов Б.Б. указан в 2х местах с id (к примеру 1001)
    и есть карточка где совпадающий с первой Иванов А.А. указан в 1х месте с id (к примеру 1002)
    то при вводе Иванов должно выпадать всего 3 варианта
    Иванов А.А. со ссылкой на id 1000
    Иванов Б.Б. со ссылкой на id 1001
    Иванов А.А. со ссылкой на id 1002

    Поле name сейчас выведет Иванов А.А Иванов Б.Б. Иванов А.А., но мне нужно только Иванов

    У меня не получается выводить только совпадение

    Как это можно сделать?
     
    #1 myks92, 15 ноя 2019
    Последнее редактирование: 15 ноя 2019
  2. Artur_hopf

    Artur_hopf Активный пользователь

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    @myks92 на кой хрен один и тот же человек имеет больше чем 1 id? переделывайте структуру бд
     
  3. myks92

    myks92 Новичок

    С нами с:
    12 июн 2018
    Сообщения:
    45
    Симпатии:
    1
    Полностью поддерживаю. Однако у меня задача реализовать только это. Переделка бд не входит в мои обязанности. Я уже сам не рад увиденному) Пока что решил сделать тремя запросами в базу в разные Таблицы. А руки таким оторвать надо. Согласен))))
     
  4. lastdays

    lastdays Активный пользователь

    С нами с:
    27 сен 2012
    Сообщения:
    410
    Симпатии:
    74
    Так если тебя интересует только Иванов, тогда зачем в запросе используешь Ф,.О. ? Отбрось их. Либо группируй по имени.
    Или я задачу не ясно понял :)
     
  5. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.076
    Симпатии:
    1.237
    Адрес:
    там-сям
    А я не понял что значит наилучшее совпадение. Это помоему ключевой момент :) Как хотелку сформулируешь, так и поедет.
     
  6. Artur_hopf

    Artur_hopf Активный пользователь

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    Я кажись догнал что он хочет. Ему надо вывести только одну фамилию Иванов, без инициалов.
    Только хз зачем, и к чему там id
     
  7. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.076
    Симпатии:
    1.237
    Адрес:
    там-сям
    Нахуа такое желать?
     
  8. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.076
    Симпатии:
    1.237
    Адрес:
    там-сям
    я понял, как мне кажется! :)

    если у этих ивановых разные id, то нет смысла выводить склеенную строку из трех разных таблиц, в одной из которых есть иванов. значит здесь не нужен не только WS_CONCAT(), но и join-ы.
    реально надо три запроса!!! но их можно склеить "вертикально", а не "горизонтально" — через операцию union.
    я не знаю как на этом построителе запросов применить union. это что вообще, Yii?

    на чистом и честном SQL это выглядит как-то так:
    Код (SQL):
    1. SELECT x.*
    2. FROM (
    3.   SELECT id, name FROM company
    4.   UNION
    5.   SELECT gl.client_id AS id, gl.fio AS name FROM group_listeners AS gl
    6.   UNION
    7.   SELECT gct.client_id AS id, gct.fio AS name FROM group_contacts AS gct
    8. ) AS x
    9. WHERE x.name LIKE 'Иванов%'
     
  9. myks92

    myks92 Новичок

    С нами с:
    12 июн 2018
    Сообщения:
    45
    Симпатии:
    1
    >>>>>> если у этих ивановых разные id, то нет смысла выводить склеенную строку из трех разных таблиц, в одной из которых есть иванов. значит здесь не нужен не только WS_CONCAT(), но и join-ы. реально надо три запроса!!!

    Вы, скорее всего правы. Но вот заказчику так нужно) Поэтому голову ломал. И в итоге делал так.
    PHP:
    1. //Ищем в команиях
    2.         $data = Company::find()
    3.             ->alias('gc')
    4.             ->select(['gc.client_id as client_id', 'TRIM(gc.name) as name'])
    5.             ->orWhere(['like', 'gc.name', $search])
    6.             ->asArray()
    7.             ->all();
    8.         //Если нет компаний ищем слушателей
    9.         if (empty($data)) {
    10.             $data = Company::find()
    11.                 ->alias('gc')
    12.                 ->select(['gc.client_id as client_id', 'TRIM(gl.fio) as name'])
    13.                 ->innerJoin('group_listeners as gl', 'gl.client_id = gc.id')
    14.                 ->distinct('gc.name, gl.fio, gct.fio')
    15.                 ->orWhere(['like', 'gl.fio', $search])
    16.                 ->asArray()
    17.                 ->all();
    18.         }// Если нет слушателей ищем по контактам
    19.         if (empty($data)) {
    20.             $data = Company::find()
    21.                 ->alias('gc')
    22.                 ->select(['gc.client_id as client_id', 'TRIM(gct.fio) as name'])
    23.                 ->innerJoin('group_contacts as gct', 'gct.client_id = gc.id')
    24.                 ->distinct('gc.name, gl.fio, gct.fio')
    25.                 ->orWhere(['like', 'gct.fio', $search])
    26.                 ->asArray()
    27.                 ->all();
    28.         }
    Но ваш пример поприятнее. Правда реально не понимаю зачем ему так надо. Но вот упёрся))

    >>> это что вообще, Yii?
    Да. Именно он) В тегах тоже указал. Но я разберусь как такой Union сделать на Yii2. Хотя вполне можно оставить SQL.
     
  10. Valick

    Valick Активный пользователь

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    Есть сфинкс, есть эластик, есть полнотекстовый поиск на худой конец.