给出以下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 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)发出这样的请求?*我猜这个只有在第一个问题之后才能回答问题:(
关于此主题的其他几个问题:也许整个情况都错了?我们应该以其他方式存储这些数据吗?或者也许有其他一些更有效的方法可以做到这一点?
答案 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