Запрос нескольких таблиц SQL для объектов одного типа - PullRequest
0 голосов
/ 06 июля 2011

С учетом следующей таблицы SQL (например, MySQL):

CREATE TABLE `table` (
  `id` int(11) unsigned NOT NULL,
  `lang` tinyint(3) unsigned NOT NULL,
  `data` text NOT NULL,
  PRIMARY KEY (`id`,`lang`)
) ENGINE=InnoDB

В этой таблице хранятся некоторые данные об объектах с идентификаторами id и data, которые можно записать на нескольких языках = lang. Типичный пример использования этой таблицы: нам нужно получить data для некоторого объекта с некоторым id и языком lang = 1 или хотя бы lang = 5 или любой другой язык, если не найдено строк с lang = 1 или 5 для id = 1.

Другими словами, я хочу получить информацию об объекте с id = 1 на английском или, по крайней мере, на немецком языке, но если нет - любого другого языка будет достаточно.

Это довольно простой запрос:

SELECT * FROM `table` WHERE `id` = 1
ORDER BY
  CASE WHEN `lang` = 1 THEN 1
       WHEN `lang` = 2 THEN 2
       ELSE 3
  END ASC
LIMIT 1

Этот запрос довольно быстрый и использует только ПЕРВИЧНЫЙ ключ с сортировкой в ​​памяти.

Вопросы появляются, когда мы хотим получить такие данные для нескольких объектов одним запросом. Единственное, о чем я могу думать, это что-то вроде:

SELECT id, (SUBQUERY TO GET DATA AS ABOVE WHERE id = tmp.id LIMIT 1) AS data
FROM (SUBQUERY TO SELECT ids) as tmp

Этот запрос выполнит свою работу, но выглядит и выглядит ужасно: /

И это первый вопрос: - это хороший и правильный способ делать такие вещи? Кто-нибудь знает лучший способ решения таких проблем?

Теперь давайте подумаем о высоконагруженных и действительно больших таблицах данных. Например, предположим, что мы дали 1 000 000 объектов с 5–15 языками для каждого. Это действительно огромная таблица для MySQL, поэтому мы разделим одну таблицу на несколько (скажем, 20 таблиц на нескольких серверах). Теперь у нас есть простая хеш-функция (например, id% N == 0), чтобы узнать, где хранятся данные для конкретного объекта.

Итак, вопрос № 2 : * Как сделать такие запросы по нескольким таблицам (даже в одной базе данных, от table_1 до table_5), если мы уже знаем, где находятся данные? * Я предполагаю, что этот вопрос можно ответить только после первого: (

Несколько других вопросов по этой теме : может быть, вся ситуация не так? Должны ли мы хранить такие данные другим способом? Или, может быть, есть другие, более эффективные способы сделать это?

1 Ответ

1 голос
/ 06 июля 2011

Вы предлагаете

SELECT id, (SUBQUERY TO GET DATA AS ABOVE WHERE id = tmp.id LIMIT 1) AS data
FROM (SUBQUERY TO SELECT ids) as tmp

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

SELECT
    `table`.`id`,
    `table`.`lang`,
    `table`.`data`
FROM
    `table`
    JOIN (
        SELECT
            `id`,
            MAX(`evaluatelanguage`(`lang`)) AS `bestscore`
        FROM
            `table` AS `sqtable`
        GROUP BY
            `id`
    ) AS `subquery` ON
        `table`.`id` = `subquery`.`id` AND
        `evaluatelanguage`(`table`.`lang`) = `subquery`.`bestscore`

NB.Эта версия требует, чтобы вы давали отдельный рейтинг каждому языку, потому что в противном случае вы увидите несколько строк, в которых идентификатор попадает в предложение ELSE в вашем CASE.Я думаю, что этот запрос может быть улучшен (конечно, нам не нужно использовать <code>evaluatelanguage столько раз?), Но я не уверен, как лучше это сделать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...