1

状況:

私はメインテーブルを持っています。それを呼び出しましょうMainTable

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

という 2 番目のテーブル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       |
+---------+-----------+-----------+------------+----------+

また、翻訳されたフィールドを検索する必要があるTEMPORARY TABLEため、 a を使用できると考えたのですが、「どの SELECT クエリを使用すればよいか」という問題が発生しました。ピボット テーブル クエリに関するいくつかの投稿を読みましたが、クエリを作成する方法がよくわからないため、一時テーブルは次のようなものです

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

ありがとうございました。

編集:

MainTable の 500.000 エントリと Translations の 1.500.000 エントリの場合、他のエントリよりも約 30 倍高速であるため、AD7six の回答を受け入れました。

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)

TranslationsTable に一致するものがない MainTable の (未翻訳の) 行を含める場合は、INNER JOIN を LEFT OUTER JOIN に変更します。

もう 1 つの方法は、ピボットを手動で実行することです。

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

それは複雑ではありません

これは、翻訳されたフィールドごとに 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 に答える