MySQL: эффективно получить одну строку для каждого элемента в предложении IN - PullRequest
4 голосов
/ 13 мая 2011

У меня есть база данных MySQL с большим количеством таблиц, и у меня есть две таблицы, которые связаны друг с другом в отношениях «многие ко многим» с использованием третьей таблицы. Вот упрощенная демонстрация того, как это выглядит:

Таблица 1: книги

  • Строка 1: ID: 15 Название: Dummy Testbook 1
  • Строка 2: ID: 18 Название: Dummy Testbook 4
  • Строка 3: ID: 22 Название: Dummy Testbook 6
  • Строка 4: ID: 10 Название: Dummy Testbook 8
  • Строка 5: ID: 16 Название: Тестовая тетрадь 15
  • ...

Таблица 2: авторы

  • Строка 1: ID: 4 Имя: Дэйв
  • Строка 2: ID: 8 Имя: Роберт
  • Строка 3: ID: 12 Имя: Эми

Таблица 3: books_authors

Строка 1: author_id: 4 book_id: 15 Строка 1: author_id: 8 book_id: 22 * ​​1031 * Строка 1: author_id: 8 book_id: 10 Строка 1: author_id: 12 book_id: 16

Я пытаюсь получить случайный список авторов с последней книгой для каждого автора, поэтому я получаю список со всеми идентификаторами авторов, использую некоторые сценарии для создания этого случайного списка, и затем я использую следующий запрос:

SELECT 
`books`.`ID`, 
`books`.`Name` 
FROM `books` 
  LEFT JOIN `books_authors` ON `books`.`ID` = `books_authors`.`book_id`
  LEFT JOIN `authors` ON `books_authors`.`author_id` = `authors`.`ID` 
WHERE  `authors`.`ID` IN(8, 12) 
LIMIT 1

Проблема в том, что предел 1 означает, что я получу только одну книгу, а я хочу получить две книги, по одной на каждого автора. Как я могу сделать это без запуска запроса для каждого автора? (база данных огромна, и запрос для каждого автора приведет к сканированию сервера). Если я увеличу лимит, я не обязательно получу две книги по одной, но я могу получить две книги от одного автора.

Другими словами, я хочу, чтобы ограничение было для IN, а не для всего запроса. Это возможно? и если нет, то есть ли эффективный способ делать то, что я пытаюсь сделать?

Спасибо!

David

Ответы [ 3 ]

2 голосов
/ 13 мая 2011

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

SELECT 
`books`.`ID`, 
`books`.`Name` 
FROM `books`
  INNER JOIN (
    select max(book_id), author_id
    from `books_authors`
    group by author_id) ba ON `books`.`ID` = ba.`book_id`
WHERE ba.author_id IN (8, 12)
2 голосов
/ 13 мая 2011

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

1 голос
/ 08 февраля 2012

Это не совсем ответ на этот вопрос, но он работал для меня для аналогичной проблемы.

У меня есть набор результатов из запроса со столбцами A, B, C, D, E. Как я хочу одинСтрока для любого результата типа D + E (мне все равно, какой именно), я сделал это с помощью функции «group by D, E».

35.000 + регистров, каждый столбец был varchar (30), Mysql для этой работы требуется 766 мс.

...