@Mofsy
Ехал Грека через реку. Видит Грека в реке рак.

Выборка данных из трех таблиц MySQL с условием многие к одному?

Здравствуйте уважаемые (и не очень) гики.

Очень давно мучил вопрос касаемо следующей ситуации:

Имеются три вымышленные таблицы:

1. Таблица объявлений
CREATE TABLE `ads` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`user_id` INT(11) NULL DEFAULT NULL,
	`cat_id` INT(11) NULL DEFAULT '0',
	`city_id` INT(11) NULL DEFAULT NULL,
	`phone` VARCHAR(100) NOT NULL,
	`title` VARCHAR(100) NOT NULL,
	PRIMARY KEY (`id`),
	INDEX `user_id` (`user_id`),
	INDEX `cat_id` (`cat_id`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM
AUTO_INCREMENT=0;


2. Таблица мета полей для объявлений
CREATE TABLE `ads_meta` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`ads_id` INT(11) NOT NULL,
	`name` VARCHAR(50) NOT NULL,
	`integer` INT(20) NOT NULL,
	`varchar` VARCHAR(100) NOT NULL,
	`text` TEXT NOT NULL,
	`longtext` LONGTEXT NOT NULL,
	PRIMARY KEY (`id`),
	INDEX `ads_id` (`ads_id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=0;


3. Таблица с путями к изображениям
CREATE TABLE `ads_images` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`user_id` INT(11) NOT NULL DEFAULT '0',
	`ads_id` INT(11) NOT NULL,
	`path` VARCHAR(100) NOT NULL,
	PRIMARY KEY (`id`),
	INDEX `ads_id` (`ads_id`),
	INDEX `user_id` (`user_id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=0;


Внимание вопрос
Какие образом выбрать объявления, забрав мета данные и изображения минимальным количеством запросов?
Изображений может быть много, как и мета данных к одному объявлению.

Пытался через GROUP_CONCAT(), но там ограничение на 1024 символа.
Пытался получать в цикле, но там количество запросов увеличивается пропорционально количеству запрошенных данных.
Использовать JOIN = выборка только один к одному, т.е. получается одна строка с объявлением, одна из мета данных, и одна из изображений.

Пока только решение в три запроса:
1. Выбрать объявления
2. Выбрать мета поля, исходя из идентификаторов объявлений используя IN
3. Выбрать изображения аналогичным запросом с IN

Всех заранее благодарю за развернутые ответы.
  • Вопрос задан
  • 1113 просмотров
Пригласить эксперта
Ответы на вопрос 1
@Joysi75
Немного не догоняю.
Одним запросом:
select ads.id, ads_meta.text, ads_images.path ...
from ads, ads_images, ads_meta
where ads_images.ads_id=ads.id and ads_meta.ads_id=ads.id
order by ads.id

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

Если будете разбивать на несколько запросов , то все равно объем информации пересылаемой с сервера БД не уменьшиться, да и на клиенте придется держать доп массивы, чтобы сохранять данные для будущих сравнений в IN-выражениях.

P.S. Экзотика:
1)Создайте таблицу ads_exotic ( ads_id, ads_meta_data, ads_images_data)
2) Заведите триггеры на модификацию таблиц ads_meta и ads_images, которые будут редактировать поля ads_meta_data и ads_images_data (допустим, добавляя/удаляя/изменяя через разделители отмодифицированные данные)
Ну и позже банально select * from ads_exotic where ads_id=X
Но это противоречит правилам нормализации БД.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы