Выбрать страницу

Часто возникает ситуация когда при использовании в таблицах связи один ко многим, из второй таблицы нужно выбрать только одну запись. То есть получить выборку один к одному.

Создадим таблицы для проведения тестов:

CREATE TABLE IF NOT EXISTS `t1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name_t1` varchar(10) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
CREATE TABLE IF NOT EXISTS `t2` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name_t2` varchar(10) NOT NULL,
  `id_t1` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ;


Заполним их данными:

INSERT INTO `t1` (`id`, `name_t1`) VALUES
(1, 'n1t1'),
(2, 'n2t1');
INSERT INTO `t2` (`id`, `name_t2`, `id_t1`) VALUES
(1, 'n1t2', 1),
(2, 'n2t2', 1),
(3, 'n3t2', 1),
(4, 'n4t2', 1),
(5, 'n5t2', 2),
(6, 'n6t2', 2),
(7, 'n7t2', 2),
(8, 'n8t2', 2);

Запрос для выборки данных из двух таблиц будет выглядеть так:

SELECT * FROM `t1` as `mt1` inner join `t2` as `mt2` on (`mt1`.`id`=`mt2`.`id_t1`) 

Нам осталось только придумать как выбрать только одну запись из таблицы t2. Здесь на помощь приходит под запрос, из него нам фактически нужно получить только 1 запись для каждой строки из таблицы t1. Сделать это можно использовав агрегатные функции min или max. Получаем следующий запрос.

SELECT * FROM `t1` as `mt1` inner join `t2` as `mt2` on (`mt1`.`id`=`mt2`.`id_t1`) 
WHERE `mt2`.`id` in (
    select min(`id`) from `t2` as `pt2` where `pt2`.`id_t1`=`mt1`.`id` 
)

Вообще говоря, это решение не очень красивое. Более правильно будет во вторую таблицу внести признак, какую строку привязывать при выборке один к одному и запрос вставить условие, будет более эффективно и управляемо.

SELECT * FROM `t1` as `mt1` inner join `t2` as `mt2` on (`mt1`.`id`=`mt2`.`id_t1`) 
where <проверка признака в таблице t2>

Было опубликовано 26 апреля 2013 на php-example.ru

Share This