Этот вопрос был задан и дан ответ в другом месте, но мне еще предстоит найти реальное, надежное, рабочее решение. Мне нужно создать запрос, который объединяет две таблицы, группирует их, но контролирует, какая строка возвращается. Вот упрощенная версия структуры данных:
- tbl_contact имеет поля: id, name
- tbl_phone имеет поля: id, contact_id, phone, primary
tbl_phone.contact_id - это внешний ключ для tbl_contact.id. primary - логический флаг, указывающий, какая из нескольких телефонных записей является первичной записью контакта.
Основная цель c - запросить все телефонные записи, но всегда возвращать первичную запись, если не указано c номер телефона запрашивается. Допустим, у контакта есть две телефонные записи, одна с номером «1234» и одна с номером «5678», и, скажем, последний помечен как основной. Если пользователь ищет телефон =% 1234% - нет проблем, мы возвращаем эту строку. Но если мы ищем имя контакта без фильтра телефона, оно всегда должно возвращать «5678» - первичную запись.
Самый близкий из всех, что я получил, - это подзапрос:
SELECT *
FROM (
SELECT c.id contact_id, c.name, p.phone, p.primary
FROM tbl_contact c
LEFT JOIN tbl_phone p
ON c.id = p.contact_id
WHERE [possibly searching name or phone]
ORDER BY p.primary DESC
)
GROUP BY contact_id
Таким образом, по сути, внутренний подзапрос получает все контакты + телефон, отсортированные по основному DES C - так, чтобы те, отмеченные 1, были бы перечислены первыми. Внешний запрос и группа выбирают одну запись для каждого контакта. Да, я знаю, что GROUP BY нарушает правило режима ONLY_FULL_GROUP_BY по умолчанию, но давайте просто go с ним ради обсуждения.
Как отмечено в другом месте, например: Какие поля строки возвращаются при группировании с MySQL? ... документация MySQL указывает, что GROUP BY будет возвращать строки случайным образом. НО ... большинство людей считают, что вышеупомянутое работает успешно, потому что обычно GROUP BY возвращает первую строку внутреннего подзапроса.
Однако в моей ситуации это не возвращает грести надежно И, судя по всему, я не могу придумать альтернативное решение. Пара дополнительных примечаний:
- Мне нужно иметь возможность искать все номера телефонов для контакта, поэтому я не могу применить фильтры предложений WHERE для первичного = 1 к внутреннему запросу.
- Я не могу применить фильтр предложения WHERE первичного = 1 к внешнему запросу, потому что, если они искали неосновной телефон, в результатах не будет основной телефонной записи для этого контакта.
- Производительность важна, но я хотел бы, по крайней мере, придумать что-то, что действительно работает ...
ОБНОВЛЕНИЕ: Мы работаем MySQL 5.7