1

情况:

我有主表,让我们称之为MainTable

+---------+----------+----------+----------+ 
|  Id (PK)| Title    | Text     | Type     |
+---------+----------+----------+----------+ 
|   1     | Some Text|More Stuff| A        | 
|   2     | Another  | Example  | B        | 
+---------+----------+----------+----------+ 

我有第二个表叫做TranslationsTable,其中 Id 字段是MainTable行 Id 的表示(没有外键,因为它可以引用不同的表), ObjType 是 ObjectType (与表同名), FieldName 是ObjecType 中的字段名称和值具有 ObjType 表中 FieldName 值的转换值。

+---------+-----------+-----------+------------+----------+
|   Id    | ObjType   | FieldName | Value      | Language |
+---------+-----------+-----------+------------+----------+
|   1     | MainTable | Title     | Algum Texto| PT       |
|   1     | MainTable | Text      | Mais Coisas| PT       |
+---------+-----------+-----------+------------+----------+

因为我需要在翻译后的字段中搜索,我想我可以使用 aTEMPORARY TABLE来这样做,但随后出现了“我应该使用哪个 SELECT 查询?”的问题。我阅读了一些关于数据透视表查询的帖子,但我真的不知道如何构建查询,所以我的临时表类似于

+---------+------------+------------+----------+ 
|  Id (PK)| Field_1    | Field_2    | Field_3  |
+---------+------------+------------+----------+ 
|   1     | Algum Texto| Mais Coisas| A        |  
+---------+------------+------------+----------+ 

谢谢你。

编辑:

我接受了 AD7six 的答案,因为 MainTable 中的 500.000 个条目和 Translations 中的 1.500.000 个条目大约比另一个快 30 倍。

4

2 回答 2

2
SELECT
  orig.Id,
  COALESCE(xlate.Field_1, orig.Field_1) AS Field_1,
  COALESCE(xlate.Field_2, orig.Field_2) AS Field_2,
  COALESCE(xlate.Field_3, orig.Field_3) AS Field_3
FROM MainTable orig
INNER JOIN (
  SELECT
    Id,Field_1,Field_2,Field_3
  FROM TranslationsTable
  PIVOT(MIN(Value) FOR FieldName IN (Field_1,Field_2,Field_3)) p
  WHERE ObjType = 'MainTable'
) xlate ON (orig.Id = xlate.Id)

如果要包含 MainTable 中在 TranslationsTable 中没有匹配项的(未翻译的)行,请将 INNER JOIN 更改为 LEFT OUTER JOIN

另一种选择是手动执行枢轴:

SELECT
  orig.Id,
  COALESCE(xlate.Field_1, orig.Field_1) AS Field_1,
  COALESCE(xlate.Field_2, orig.Field_2) AS Field_2,
  COALESCE(xlate.Field_3, orig.Field_3) AS Field_3
FROM MainTable orig
INNER JOIN (
  SELECT
    Id,
    MIN(CASE FieldName WHEN 'Field_1' THEN Value END) AS Field_1,
    MIN(CASE FieldName WHEN 'Field_2' THEN Value END) AS Field_2,
    MIN(CASE FieldName WHEN 'Field_3' THEN Value END) AS Field_3
  FROM TranslationsTable 
  WHERE ObjType = 'MainTable'
  GROUP BY Id
) xlate ON (orig.Id = xlate.Id)

像其他人建议的那样更改 MainTable 架构,您将不需要重复 (Field_1,Field_2,Field_3)。它使代码更易于维护和修改。

于 2013-07-03T16:50:32.607 回答
1

这并不复杂

这只是一个查询,每个翻译字段都有一个连接。

这意味着您可以像其他任何内容一样查询/排序/任何内容,例如(使用一些真实姓名以便于阅读):

SELECT
    products.id,
    COALESCE(product_name.value, products.name) as name,
    COALESCE(product_description.value, products.description) as description
FROM
    products
LEFT JOIN
    TranslationsTable AS product_name
    ON (
        product_name.Language = 'PT' AND
        product_name.ObjectType = 'products' AND
        product_name.FieldName = 'name' AND
        product_name.id = products.id
    )
LEFT JOIN
    TranslationsTable AS product_description
    ON (
        product_description.Language = 'PT' AND
        product_description.ObjectType = 'products' AND
        product_description.FieldName = 'description' AND
        product_description.id = products.id
    )
WHERE
    product_name.value = "Algum Texto" // Find all products named "Algum Texto"

你不需要临时表

但是如果你想创建一个,使用查询本身很容易:

CREATE TABLE
    products_pt
AS
SELECT
    products.id,
    COALESCE(product_name.value, products.name) as name,
    COALESCE(product_description.value, products.description) as description
...

这将创建一个与查询结构匹配的表(无索引)。如果您的数据不经常更改,它可以使查询您的多语言数据更容易管理,但有一些缺点,例如(显然)如果源表数据发生更改,您的翻译特定表将不是最新的。

于 2013-07-03T18:54:50.123 回答