0

给定以下 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 的对象的数据,id并且data可以用多种语言编写 = lang。此表的典型用例是:我们需要获取具有某个id的某个对象的数据,其中语言为lang = 1 或至少lang = 5 或任何其他语言,如果没有lang = 1 或 5 for 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

此查询非常快,并且仅使用 PRIMARY 键和内存排序。

当我们想通过一个查询获取多个对象的此类数据时,就会出现这些问题。我能想到的唯一一个是这样的:

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)发出这样的请求?* 我想这个问题只能在第一个之后才能回答:(

关于这个话题的其他几个问题:也许整个情况都是错误的?我们应该以其他方式存储这些数据吗?或者也许还有其他更有效的方法来做到这一点?

4

1 回答 1

1

You suggest

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

A small-ish change, but surely it's a bit better to join to a resultset telling you the best language for each desired row.

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. This version requires you to give a separate rank to every language, because otherwise you will see multiple rows where an id falls into the ELSE clause in your CASE. I think this query can be improved (surely we need not use evaluatelanguage so many times?) but I'm unsure how best to go about it.

于 2011-07-06T14:24:26.040 回答