M
M
Mofsy2015-11-29 13:23:59
PHP
Mofsy, 2015-11-29 13:23:59

Selecting data from three MySQL tables with a many-to-one condition?

Hello dear (and not so) geeks.
For a long time I was tormented by the question regarding the following situation:
There are three fictitious tables:
1. The declaration table

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. Table of meta fields for ads
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. Table with paths to images
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;

Attention to the question
How to select ads, taking meta data and images with a minimum number of requests?
There can be many images, as well as meta data for one ad.
I tried using GROUP_CONCAT(), but there is a limit of 1024 characters.
I tried to receive in a loop, but there the number of requests increases in proportion to the amount of requested data.
Use JOIN = select only one to one, i.e. This results in one ad line, one metadata, and one image.
So far, only a solution in three queries:
1. Select ads
2. Select meta fields based on ad IDs using IN
3. Select images with a similar query withIN
Thank you all in advance for the detailed answers.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
Marat, 2015-11-29
@Joysi75

I don't catch up a bit.
With one request:

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

open a query and inside it run through all the records in a loop, inside which to compare the current ads.id value with the value in the previous step, and based on this, generate an output or analysis.
If you break it into several queries, then the amount of information sent from the database server will not decrease anyway, and you will have to keep additional arrays on the client in order to save data for future comparisons in IN-expressions.
PS Exotic:
1) Create an ads_exotic table ( ads_id, ads_meta_data, ads_images_data)
2) Create triggers to modify the ads_meta and ads_images tables, which will edit the ads_meta_data and ads_images_data fields (for example, adding / deleting / changing the modified data through separators)
Well, later it's trite select * from ads_exotic where ads_id=X
But this is contrary to the rules of database normalization.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question