powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Как сделать выборку?
14 сообщений из 14, страница 1 из 1
Как сделать выборку?
    #32737447
Igor Pavlenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте,
есть таблица `users`
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
CREATE TABLE `users` (
  `linking_id` int( 11 ) unsigned NOT NULL auto_increment,
  `user_id` int( 11 ) unsigned NOT NULL default '0',
  `company` varchar( 255 ) NOT NULL default '',
  `street_address` varchar( 255 ) NOT NULL default '',
  `building` varchar( 255 ) NOT NULL default '',
  `zip_code` varchar( 255 ) NOT NULL default '',
  `city` varchar( 255 ) NOT NULL default '',
  `country_id` int( 11 ) unsigned NOT NULL default '0',
  `language_id` int( 11 ) unsigned NOT NULL default '0',
  `telephone` varchar( 255 ) NOT NULL default '',
  `fax` varchar( 255 ) NOT NULL default '',
  `office_email` varchar( 255 ) default NULL,
  `company_homepage` varchar( 255 ) default NULL,
  `annual_turnover_id` int( 11 ) unsigned NOT NULL default '0',
  `employees_id` int( 11 ) unsigned NOT NULL default '0',
  `uid_nr` varchar( 255 ) NOT NULL default '',
  `headquarters_1` varchar( 255 ) default NULL,
  `headquarters_2` varchar( 255 ) default NULL,
  `headquarters_3` varchar( 255 ) default NULL,
  `mother_company` varchar( 255 ) default NULL,
  `company_type_id` int( 11 ) unsigned NOT NULL default '0',
  `comments` varchar( 255 ) NOT NULL default '',
  `password` varchar( 255 ) NOT NULL default '',
  `password_clue_id` int( 11 ) unsigned NOT NULL default '0',
  `password_clue_answer` varchar( 255 ) NOT NULL default '',
  PRIMARY KEY  (`linking_id`),
  KEY `user_id` (`user_id`),
  KEY `country_id` (`country_id`),
  KEY `annual_turnover` (`annual_turnover_id`),
  KEY `employees_id` (`employees_id`),
  FULLTEXT KEY `company` (`company`),
  FULLTEXT KEY `comments` (`comments`),
  FULLTEXT KEY `password` (`password`)
) TYPE=MyISAM;

И есть еще одна таблица,
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
CREATE TABLE `users_in_branches` (
  `id` int( 11 ) unsigned NOT NULL auto_increment,
  `linking_id` int( 11 ) unsigned NOT NULL default '0',
  `branch_id` int( 11 ) unsigned NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `product_id` (`linking_id`),
  KEY `sales_branch_id` (`branch_id`)
) TYPE=MyISAM;

и
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
CREATE TABLE `branches` (
  `id` int( 11 ) unsigned NOT NULL auto_increment,
  `branch_id` int( 11 ) unsigned NOT NULL default '0',
  `branch` varchar( 255 ) NOT NULL default '',
  `language_id` int( 11 ) unsigned NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `branch_id` (`branch_id`),
  KEY `language_id` (`language_id`)
) TYPE=MyISAM;

Эти первые две таблички связаны полем
Код: plaintext
linking_id
. А последние две - полем
Код: plaintext
branch_id
.
В таблице `users_in_branches` хранятся номера категорий к которым принадлежит пользователь, т.е. он может принадлежать сразу более чем к одной категории (т.е. сколько там будет категорий, тоже не ограничено).
В таблице `branches` хранятся названия этих самых категорий на разных языках, т.е. поле `language_id` определяет каждую строку как категорию на указанном языке.

Теперь самое главное. Как сделать выборку, так, чтобы вся нужная информация была в таком виде:

Код: plaintext
user_id | company | еще_др._поля_из_табл._users | ТУТ КАТЕГОРИИ К КОТОРЫМ ПРИНАДЛЕЖИТ ПОЛЬЗОВАТЕЛЬ

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

Если можете подскажите пожалуйста.

Огромное спасибо.
...
Рейтинг: 0 / 0
Как сделать выборку?
    #32738135
wlck
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
вообще-то, обычно я делаю подобное в клиенте (php, ...)
но, можно так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
SET @list = '';

SELECT users.user_id, users.company,
# другие поля
@list := CONCAT(@list, IF(LENGTH(@list), ',', ''), branches.branch) AS BranchList
FROM users INNER JOIN users_in_branches USING(linking_id)
INNER JOIN branches USING(branch_id)
WHERE users.user_id =  1 
ORDER BY BranchList DESC
LIMIT  1 
...
Рейтинг: 0 / 0
Как сделать выборку?
    #32738236
wlck
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
а заменив CONCAT(@list, ...
на CONCAT_WS('', @list, ...) можно одним запросом
...
Рейтинг: 0 / 0
Как сделать выборку?
    #32738448
Фотография Хрен
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Начиная с 4.1 появилась агрегатная функция group_concat которая делает список из значений поля выборки.

GROUP_CONCAT([DISTINCT] expr [,expr ...]
[ORDER BY {unsigned_integer | col_name | expr}
[ASC | DESC] [,col_name ...]]
[SEPARATOR str_val])
...
Рейтинг: 0 / 0
Как сделать выборку?
    #32738617
wlck
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
4.1 ещё не stable, я бы пока не стал бы эту версию юзать
...
Рейтинг: 0 / 0
Как сделать выборку?
    #32738626
Фотография Хрен
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
4.1 это гамма. То что у других называется уже stable
...
Рейтинг: 0 / 0
Как сделать выборку?
    #32741316
Igor Pavlenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо за ответы. Но я решил сделать чуть по другому, НО тут получается так, что мой запрос выполняется 31 сек на P2-266/256Mb, 2.1 сек на Duron 1.4/512Mb, что неприемлимо...
Вот запрос:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
SELECT
        users.user_id,
        users.company,
        users.street_address,
        users.building,
        users.zip_code,
        users.city,
        countries.country,
        languages.language,
        users.telephone,
        users.fax,
        users.office_email,
        users.company_homepage,
        annual_turnovers.turnover,
        employees.employees_value,
        users.uid_nr,
        users.headquarters_1,
        users.headquarters_2,
        users.headquarters_3,
        users.mother_company,
        company_types.company_type,
        users.comments,
        password_clues.clue,
        users.password_clue_answer,
        
        T1.title,
        EUT1.first_name,
        EUT1.last_name,
        EUT1.extension,
        EUT1.mobile,
        EUT1.fax,
        EUT1.email,
        
        T2.title,
        EUT2.first_name,
        EUT2.last_name,
        EUT2.extension,
        EUT2.mobile,
        EUT2.fax,
        EUT2.email,
        
        T3.title,
        EUT3.first_name,
        EUT3.last_name,
        EUT3.extension,
        EUT3.mobile,
        EUT3.fax,
        EUT3.email
        
      FROM
        users,
        countries,
        languages,
        annual_turnovers,
        employees,
        company_types,
        password_clues,
        titles AS T1,
        titles AS T2,
        titles AS T3
        LEFT JOIN extra_users AS EUT1 on (EUT1.linking_id=users.linking_id AND EUT1.user_number='1')
        LEFT JOIN extra_users AS EUT2 on (EUT2.linking_id=users.linking_id AND EUT2.user_number='2')
        LEFT JOIN extra_users AS EUT3 on (EUT3.linking_id=users.linking_id AND EUT3.user_number='3')
        
      WHERE
        countries.country_id=users.country_id
        AND
        languages.language_id='48'
        AND
        (annual_turnovers.annual_turnover_id=users.annual_turnover_id AND annual_turnovers.language_id='48')
        AND
        (employees.employees_id=users.employees_id AND employees.language_id='48')
        AND
        (company_types.company_type_id=users.company_type_id AND company_types.language_id='48')
        AND
        (password_clues.password_clue_id=users.password_clue_id AND password_clues.language_id='48')
        AND
        (T1.title_id=EUT1.title_id AND T1.language_id='48')
        AND
        (T2.title_id=EUT2.title_id AND T2.language_id='48')
        AND
        (T3.title_id=EUT3.title_id AND T3.language_id='48')
      ORDER BY users.company

Причем, что интересно, если убрать строки
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
 
        ...
        T1.title,
        ...
        T2.title,
        ...
        T3.title,
        ...       
        titles AS T1,
        titles AS T2,
        titles AS T3      
        ...
        (T1.title_id=EUT1.title_id AND T1.language_id='48')
        AND
        (T2.title_id=EUT2.title_id AND T2.language_id='48')
        AND
        (T3.title_id=EUT3.title_id AND T3.language_id='48')
То запрос обрабатывается мгновенно (0.03 сек).
Так чем же они так тормозят эти строки?

Спасибо.
...
Рейтинг: 0 / 0
Как сделать выборку?
    #32741385
Фотография Хрен
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
покажи explain
...
Рейтинг: 0 / 0
Как сделать выборку?
    #32741423
Igor Pavlenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3038 to server version: 4.0.18
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
+------------------+--------+-------------------------------------------------+-------------+---------+------------------+------+---------------------------------+
| table            | type   | possible_keys                                   | key         | key_len | ref              | rows | Extra                           |
+------------------+--------+-------------------------------------------------+-------------+---------+------------------+------+---------------------------------+
| languages        | const  | PRIMARY,language_id                             | PRIMARY     |       4 | const            |    1 | Using temporary; Using filesort |
| company_types    | ref    | company_type_id,language_id                     | language_id |       4 | const            |    2 | Using where                     |
| password_clues   | ref    | password_clue_id,language_id                    | language_id |       4 | const            |    1 | Using where                     |
| annual_turnovers | ref    | annual_turnover_id,language_id                  | language_id |       4 | const            |    7 |                                 |
| T1               | ALL    | title_id,language_id                            | NULL        |    NULL | NULL             |    6 | Using where                     |
| EUT3             | ref    | linking_id,user_number                          | user_number |       1 | const            |    1 | Using where                     |
| EUT1             | ref    | linking_id,user_number                          | user_number |       1 | const            |    1 | Using where                     |
| EUT2             | ref    | linking_id,user_number                          | user_number |       1 | const            |    1 | Using where                     |
| T2               | ALL    | title_id,language_id                            | NULL        |    NULL | NULL             |    6 | Using where                     |
| T3               | ALL    | title_id,language_id                            | NULL        |    NULL | NULL             |    6 | Using where                     |
| employees        | ALL    | employees_id,language_id                        | NULL        |    NULL | NULL             |    9 | Using where                     |
| users            | eq_ref | PRIMARY,country_id,annual_turnover,employees_id | PRIMARY     |       4 | EUT1.linking_id  |    1 | Using where                     |
| countries        | eq_ref | PRIMARY                                         | PRIMARY     |       4 | users.country_id |    1 |                                 |
+------------------+--------+-------------------------------------------------+-------------+---------+------------------+------+---------------------------------+
13 rows in set (20.86 sec)
...
Рейтинг: 0 / 0
Как сделать выборку?
    #32741424
Igor Pavlenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А вот структура таблиц `titles` :

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
CREATE TABLE `titles` (
  `id` int( 11 ) unsigned NOT NULL auto_increment,
  `title_id` int( 11 ) unsigned NOT NULL default '0',
  `title` varchar( 255 ) NOT NULL default '',
  `language_id` int( 11 ) unsigned NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `title_id` (`title_id`),
  KEY `language_id` (`language_id`)
) TYPE=MyISAM;

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
CREATE TABLE `users_in_branches` (
  `id` int( 11 ) unsigned NOT NULL auto_increment,
  `linking_id` int( 11 ) unsigned NOT NULL default '0',
  `branch_id` int( 11 ) unsigned NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `linking_id` (`linking_id`),
  KEY `branch_id` (`branch_id`)
) TYPE=MyISAM;

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
CREATE TABLE `extra_users` (
  `id` int( 11 ) unsigned NOT NULL auto_increment,
  `linking_id` int( 11 ) unsigned NOT NULL default '0',
  `user_number` tinyint( 4 ) unsigned NOT NULL default '0',
  `title_id` int( 11 ) unsigned NOT NULL default '0',
  `first_name` varchar( 255 ) NOT NULL default '',
  `last_name` varchar( 255 ) NOT NULL default '',
  `extension` varchar( 255 ) NOT NULL default '',
  `mobile` varchar( 255 ) default NULL,
  `fax` varchar( 255 ) NOT NULL default '',
  `email` varchar( 255 ) NOT NULL default '',
  PRIMARY KEY  (`id`),
  KEY `linking_id` (`linking_id`),
  KEY `user_number` (`user_number`)
) TYPE=MyISAM;

Код: plaintext
1.
2.
3.
4.
5.
6.
CREATE TABLE `languages` (
  `language_id` int( 11 ) unsigned NOT NULL auto_increment,
  `language` varchar( 255 ) NOT NULL default '',
  `iso_code` varchar( 4 ) default NULL,
  PRIMARY KEY  (`language_id`),
  KEY `language_id` (`language_id`)
) TYPE=MyISAM;

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
CREATE TABLE `employees` (
  `id` int( 11 ) unsigned NOT NULL auto_increment,
  `employees_id` int( 11 ) unsigned NOT NULL default '0',
  `employees_value` varchar( 255 ) NOT NULL default '',
  `language_id` int( 11 ) unsigned NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `employees_id` (`employees_id`),
  KEY `language_id` (`language_id`)
) TYPE=MyISAM;

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
CREATE TABLE `annual_turnovers` (
  `id` int( 11 ) unsigned NOT NULL auto_increment,
  `annual_turnover_id` int( 11 ) unsigned NOT NULL default '0',
  `turnover` varchar( 255 ) NOT NULL default '',
  `language_id` int( 11 ) unsigned NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `annual_turnover_id` (`annual_turnover_id`),
  KEY `language_id` (`language_id`)
) TYPE=MyISAM;

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
CREATE TABLE `company_types` (
  `id` int( 11 ) unsigned NOT NULL auto_increment,
  `company_type_id` int( 11 ) unsigned NOT NULL default '0',
  `company_type` varchar( 255 ) NOT NULL default '',
  `language_id` int( 11 ) unsigned NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `company_type_id` (`company_type_id`),
  KEY `language_id` (`language_id`)
) TYPE=MyISAM;

Вроде все. :-)
...
Рейтинг: 0 / 0
Как сделать выборку?
    #32741695
wlck
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
уважаемый, то что у вас данный запрос вообще выполняется - чудо (видимо мало записей)
при join'ax очень желательно :)) использовать индексы, чтобы не получать следующее:
Код: plaintext
T1               | ALL    | title_id,language_id                            | NULL
если при explain вылезает ALL, то нужно что-то менять (например индексы)
...
Рейтинг: 0 / 0
Как сделать выборку?
    #32741768
Фотография Хрен
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Igor PavlenkoWelcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3038 to server version: 4.0.18
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
+------------------+--------+-------------------------------------------------+-------------+---------+------------------+------+---------------------------------+
| table            | type   | possible_keys                                   | key         | key_len | ref              | rows | Extra                           |
+------------------+--------+-------------------------------------------------+-------------+---------+------------------+------+---------------------------------+
| languages        | const  | PRIMARY,language_id                             | PRIMARY     |       4 | const            |    1 | Using temporary; Using filesort |
| company_types    | ref    | company_type_id,language_id                     | language_id |       4 | const            |    2 | Using where                     |
| password_clues   | ref    | password_clue_id,language_id                    | language_id |       4 | const            |    1 | Using where                     |
| annual_turnovers | ref    | annual_turnover_id,language_id                  | language_id |       4 | const            |    7 |                                 |
| T1               | ALL    | title_id,language_id                            | NULL        |    NULL | NULL             |    6 | Using where                     |
| EUT3             | ref    | linking_id,user_number                          | user_number |       1 | const            |    1 | Using where                     |
| EUT1             | ref    | linking_id,user_number                          | user_number |       1 | const            |    1 | Using where                     |
| EUT2             | ref    | linking_id,user_number                          | user_number |       1 | const            |    1 | Using where                     |
| T2               | ALL    | title_id,language_id                            | NULL        |    NULL | NULL             |    6 | Using where                     |
| T3               | ALL    | title_id,language_id                            | NULL        |    NULL | NULL             |    6 | Using where                     |
| employees        | ALL    | employees_id,language_id                        | NULL        |    NULL | NULL             |    9 | Using where                     |
| users            | eq_ref | PRIMARY,country_id,annual_turnover,employees_id | PRIMARY     |       4 | EUT1.linking_id  |    1 | Using where                     |
| countries        | eq_ref | PRIMARY                                         | PRIMARY     |       4 | users.country_id |    1 |                                 |
+------------------+--------+-------------------------------------------------+-------------+---------+------------------+------+---------------------------------+
13 rows in set (20.86 sec)


Вот посмотрите. там где ALL - это простой перебор записей без всяких индексов. То есть к примеру emplyees ALL - означает что для каждой найденной записи languages и для каждой найденной company_types и тд (то есть практически для всех найденных записей всех таблиц) будет делаться полный просмотр всех записей в employees.

Учитывая что таких таблиц c ALL несколько в explain, понятно, что такой запрос - будет тормозить. Причем по мере наполнения базы, тормоза будут расти в степенной зависимости.

Вам сейчас надо - присмотреться поподробнее к таблицам, которые с ALL в explain, создать индексы, если индексы уже есть, но не используются, попробовать USE INDEX или FORCE INDEX.
...
Рейтинг: 0 / 0
Как сделать выборку?
    #32741941
Igor Pavlenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да, действительно, подобрав индексы получил быструю выборку. Правда я не уверен, что я подобрал оптимальное количество индексов :-), мне кажется что я немного перестарался.
Есть ли смысл создавать такие индексы вместе:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
  PRIMARY KEY  (`linking_id`),
  KEY `user_id` (`user_id`),
  KEY `country_id` (`country_id`),
  KEY `annual_turnover` (`annual_turnover_id`),
  KEY `employees_id` (`employees_id`),
  KEY `linking_id` (`linking_id`),
  KEY `company_type_id` (`company_type_id`),
  KEY `group1` (`linking_id`,`country_id`,`language_id`,`annual_turnover_id`,`employees_id`,`company_type_id`),
  KEY `password_clue_id` (`password_clue_id`),
  KEY `status` (`status`),
  FULLTEXT KEY `company` (`company`),
  FULLTEXT KEY `comments` (`comments`),
  FULLTEXT KEY `password` (`password`)

Т.е. создавать multiple-column index и одиночные индексы, которые ссылаются на одинаковые поля. (Выше это индекс group1 и скажем country_id , annual_turnover )?

Огромное спасибо всем за помощь!
...
Рейтинг: 0 / 0
Как сделать выборку?
    #32745122
maXmo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
как я понял, индексов нужно столько, чтобы all исчез, не больше.
ma X mo
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Как сделать выборку?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]