Mysql 数据库问题:从表中获取默认翻译
你好 我有一个MySQL表description,它包含诸如:lang\u id、label、short\u description、long\u description等字段,并且是默认值 在我的应用程序中,产品描述是根据当前语言从数据库中获取的。目前一切正常,但是我想为每个产品添加一个默认描述,以便在找不到所需语言的描述时,取而代之的是默认描述 现在,我的请求如下所示:Mysql 数据库问题:从表中获取默认翻译,mysql,database,Mysql,Database,你好 我有一个MySQL表description,它包含诸如:lang\u id、label、short\u description、long\u description等字段,并且是默认值 在我的应用程序中,产品描述是根据当前语言从数据库中获取的。目前一切正常,但是我想为每个产品添加一个默认描述,以便在找不到所需语言的描述时,取而代之的是默认描述 现在,我的请求如下所示: SELECT description.id AS record_id description.labe
SELECT
description.id AS record_id
description.label,
description.short_description,
description.long_description
FROM
products,
description,
languages
WHERE
products.id = '.$someProductID.' AND
products.id = description.product_id AND
languages.id = description.lang_id AND
languages.code = "'.$someLang.'"
IFNULL(description.label, (SELECT label FROM description WHERE product_id = '.$someProductID.' AND is_default = 1) ) AS label
CREATE VIEW descriptionView AS
SELECT
languages.code as lang,
descriptions.code,
IFNULL(t1.label, t2.label) AS label,
IFNULL(t1.short_description, t2.short_description) AS short_description,
IFNULL(t1.long_description, t2.long_description) AS long_description
FROM
descriptions,
languages
LEFT JOIN
translations t1
ON
t1.description_id = descriptions.id AND t1.lang_id = languages.id
LEFT JOIN
translations t2
ON
t2.description_id = descriptions.id AND t2.is_default = 1
当所需的翻译不存在时,是否有人能找到获取产品默认描述的解决方案
我想在我的请求中添加一些IFNULL语句,如下所示:
SELECT
description.id AS record_id
description.label,
description.short_description,
description.long_description
FROM
products,
description,
languages
WHERE
products.id = '.$someProductID.' AND
products.id = description.product_id AND
languages.id = description.lang_id AND
languages.code = "'.$someLang.'"
IFNULL(description.label, (SELECT label FROM description WHERE product_id = '.$someProductID.' AND is_default = 1) ) AS label
CREATE VIEW descriptionView AS
SELECT
languages.code as lang,
descriptions.code,
IFNULL(t1.label, t2.label) AS label,
IFNULL(t1.short_description, t2.short_description) AS short_description,
IFNULL(t1.long_description, t2.long_description) AS long_description
FROM
descriptions,
languages
LEFT JOIN
translations t1
ON
t1.description_id = descriptions.id AND t1.lang_id = languages.id
LEFT JOIN
translations t2
ON
t2.description_id = descriptions.id AND t2.is_default = 1
但我对这种复杂的查询不是很熟悉,我无法使它工作
我愿意接受建议;)
谢谢大家! 这个:
SELECT p.*, COALESCE (dn.name, den.name) AS cname
FROM products p
LEFT JOIN
description dn
ON dn.product_id = p.id
AND dn.language =
(
SELECT id
FROM language
WHERE code = 'your_language'
)
LEFT JOIN
description den
ON den.product_id = p.id
AND den.is_default
)
WHERE p.id = @my_product
,或这个:
SELECT p.*,
COALESCE (dn.name,
(
SELECT den.name
FROM description den
WHERE den.product_id = p.id
AND den.is_default
)
) AS cname
FROM products p
LEFT JOIN
description dn
ON dn.product_id = p.id
AND dn.language =
(
SELECT id
FROM language
WHERE code = 'your_language'
)
WHERE p.id = @my_product
在除MySQL之外的所有数据库中,第一个数据库在您的语言翻译较少时效率更高,第二个数据库在您的语言翻译较多时效率更高
在MySQL
中,第二个查询(使用COALESCE
)总是更高效
有关性能详细信息,请参阅我的博客中关于此问题的这一系列文章:
,并进一步导航到其他
RDBMS,您可以在另一个别名(例如,默认值)下再次加入描述表,其中您仅从默认语言提取结果。不确定这是否比您的IFNULL想法更影响性能。您可以提前获取语言ID并使用它们正确构建查询:
// this code is performed once and the results are stored for use in all description lookups
SELECT id INTO :def_lang_id FROM languages WHERE code = :default_lang_code;
SELECT id INTO :usr_lang_id FROM languages WHERE code = :user_lang_code;
// this is an example of using the above results to speed your search for the "correct" descriptions
if ($def_lang_id == $usr_lang_id) {
$sql = "SELECT d.id, d.label, d.short_desc, d.long_desc
FROM products p, description d
WHERE p.id = :some_prod_id
AND p.id = d.product_id
AND d.lang_id = :usr_lang_id";
} else {
$orderdirection = $def_lang_id < $usr_lang_id ? "DESC" : "ASC";
$sql = "SELECT d.id, d.label, d.short_desc, d.long_desc
FROM products p, description d
WHERE p.id = :some_prod_id
AND p.id = d.product_id
AND d.lang_id in (:def_lang_id, :usr_lang_id)
ORDER BY d.lang_id $langdirection";
}
//此代码执行一次,并存储结果以供在所有描述查找中使用
从语言中选择id:def_lang_id,其中code=:default_lang_code;
从语言中选择id:usr\u lang\u id,其中code=:user\u lang\u code;
//这是一个使用上述结果加快搜索“正确”描述的示例
如果($def_lang_id==$usr_lang_id){
$sql=“选择d.id、d.label、d.short\u desc、d.long\u desc
来自产品p,描述d
其中p.id=:一些产品id
p.id=d.product\u id
和d.lang_id=:usr_lang_id”;
}否则{
$orderdirection=$def_lang_id<$usr_lang_id?“描述”:“ASC”;
$sql=“选择d.id、d.label、d.short\u desc、d.long\u desc
来自产品p,描述d
其中p.id=:一些产品id
p.id=d.product\u id
和d.lang_id in(:def_lang_id,:usr_lang_id)
d.lang_id$langdirection订购”;
}
现在,如果用户使用的是默认语言,那么它只会得到一个描述。如果他们使用不同的语言,则备用语言的lang_id将在查询中的默认_id值之前排序。因此,如果有备用描述,则在查询的第一行返回,如果没有备用描述,则只返回默认描述
这段代码的另一个明显的好处是我们不需要每次都加入语言表。谢谢你们的帮助,伙计们,我正在接近解决方案
@jmucchiello:我不是在寻找PHP端验证。我希望MySQL完成所有工作,因为我将在许多其他SQL查询中使用它
换句话说,我想提出这个请求,将它存储在一个视图中,以便以一种简化的方式获得我的产品的翻译描述。类似于:descriptionView
然后我会这样使用它:
SELECT * FROM descriptionView WHERE lang_code = "en" AND product_id = 80007
这就是我现在所拥有的:
SELECT
descriptions.code,
IFNULL(t1.label, t2.label) AS label,
IFNULL(t1.short_description, t2.short_description) AS short_description,
IFNULL(t1.long_description, t2.long_description) AS long_description
FROM
descriptions
LEFT JOIN
translations t1
ON
t1.description_id = descriptions.id AND t1.lang_id =
(
SELECT
id
FROM
languages
WHERE
code = "fr"
)
LEFT JOIN
translations t2
ON
t2.description_id = descriptions.id AND t2.is_default = 1
WHERE
descriptions.id = 1
它工作正常,但是我需要删除硬编码的“1”和“fr”,因为我想在一个收集所有条目的视图中对其进行转换,然后在该视图上执行选择
问题是,由于某些原因,我无法将第一个左连接更改为:
LEFT JOIN
translations t1
ON
t1.description_id = descriptions.id AND t1.lang_id = languages.id
并在FROM子句中添加语言
最后,我要删除WHERE子句,因为我需要所有结果
因此,我的最终查询如下所示:
SELECT
description.id AS record_id
description.label,
description.short_description,
description.long_description
FROM
products,
description,
languages
WHERE
products.id = '.$someProductID.' AND
products.id = description.product_id AND
languages.id = description.lang_id AND
languages.code = "'.$someLang.'"
IFNULL(description.label, (SELECT label FROM description WHERE product_id = '.$someProductID.' AND is_default = 1) ) AS label
CREATE VIEW descriptionView AS
SELECT
languages.code as lang,
descriptions.code,
IFNULL(t1.label, t2.label) AS label,
IFNULL(t1.short_description, t2.short_description) AS short_description,
IFNULL(t1.long_description, t2.long_description) AS long_description
FROM
descriptions,
languages
LEFT JOIN
translations t1
ON
t1.description_id = descriptions.id AND t1.lang_id = languages.id
LEFT JOIN
translations t2
ON
t2.description_id = descriptions.id AND t2.is_default = 1
然后,我可以使用以下方法查询该视图:
SELECT * FROM descriptionView WHERE lang_code = "en" AND product_id = 80007
您的第一个示例看起来不错,但我不太明白您的语法。还有,身份证,什么是“我”?这是一个错误吗?你介意用我在问题中使用的格式改写你的第一个例子吗?这将真正帮助我理解,并允许我尝试。谢谢@doM
:很抱歉,刚刚从我的博客中复制了它,没有修复所有名称。请稍等!说我的数据库不存在COALESCE函数。我正在使用MySQL 5.0.51a@doM
:这很奇怪。只需使用IFNULL