MySQL использует IN / FIND_IN_SET для чтения нескольких строк в подзапросе - PullRequest
2 голосов
/ 17 января 2012

У меня есть две таблицы, местоположения и группы местоположений

CREATE TABLE locations (
    location_id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(63) UNIQUE NOT NULL
);

INSERT INTO locations (name)
  VALUES
('london'),
('bristol'),
('exeter');

CREATE TABLE location_groups (
    location_group_id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    location_ids VARCHAR(255) NOT NULL,
    user_ids VARCHAR(255) NOT NULL,
    name VARCHAR(63) NOT NULL,
);

INSERT INTO location_groups (location_ids, user_ids, name)
  VALUES
('1', '1,2,4', 'south east'),
('2,3', '2', 'south west');

Я пытаюсь вернуть все location_ids для всех location_groups, где существует указанный user_id.Я использую CSV для хранения location_ids и user_ids в таблице location_groups.Я знаю, что это не нормализовано, но такова база данных, и она находится вне моего контроля.

Мой текущий запрос:

SELECT location_id 
  FROM locations 
  WHERE FIND_IN_SET(location_id, 
      (SELECT location_ids 
         FROM location_groups 
         WHERE FIND_IN_SET(2,location_groups.user_ids)) )

Теперь это работает нормально, если user_id =1, например (так как возвращается только 1 строка location_group), но если я ищу user_id = 2, я получаю сообщение об ошибке, говорящее, что подзапрос возвращает более 1 строки, что ожидается, поскольку пользователь 2 находится в 2 location_groups.Я понимаю, почему выдается ошибка, я пытаюсь решить, как ее решить.

Чтобы уточнить при поиске user_id 1 в location_groups.user_ids, location_id 1 должен быть возвращен.При поиске user_id 2 должны быть возвращены location_ids 1,2,3.

Я знаю, что это сложный запрос, поэтому, если что-то не понятно, просто дайте мне знать.Любая помощь будет оценена!Спасибо.

1 Ответ

3 голосов
/ 17 января 2012

Вы можете использовать GROUP_CONCAT для объединения location_id s в подзапросе.

SELECT location_id 
FROM locations 
WHERE FIND_IN_SET(location_id, 
    (SELECT GROUP_CONCAT(location_ids)
     FROM location_groups 
     WHERE FIND_IN_SET(2,location_groups.user_ids)) )

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

...