查询一种类型对象的多个SQL表

时间:2011-07-06 14:12:15

标签: mysql crosstab sql

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

换句话说,我希望获得关于id = 1的对象的信息在英语或至少在Deutsch上,但如果没有 - 任何其他语言就足够了。

这是一个相当简单的查询:

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

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

1 个答案:

答案 0 :(得分:1)

你建议

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。此版本要求您为每种语言提供单独的排名,否则您将看到多行,其中id属于ELSE中的CASE子句。我认为这个查询可以改进(当然我们不需要多次使用evaluatelanguage?)但我不确定如何最好地解决它。