2016-08-30 11 views
2

とMySQLの変換テーブルに私はこのようなデータベース構造を持っている:不足している言語のフォールバック

CREATE TABLE IF NOT EXISTS `countries` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `code` varchar(2) COLLATE utf8_unicode_ci NOT NULL, 
    `is_active` tinyint(1) NOT NULL, 
    `created_at` datetime NOT NULL, 
    `updated_at` datetime NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `UNIQ_5D66EBAD77153098` (`code`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

国の言語

CREATE TABLE IF NOT EXISTS `country_languages` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `language_id` int(11) DEFAULT NULL, 
    `country_id` int(11) DEFAULT NULL, 
    `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `created_at` datetime NOT NULL, 
    `updated_at` datetime NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `IDX_1532561982F1BAF4` (`language_id`), 
    KEY `IDX_15325619F92F3E70` (`country_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

言語

CREATE TABLE IF NOT EXISTS `languages` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `iso` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `active` tinyint(1) NOT NULL DEFAULT '1', 
    `is_primary` tinyint(1) DEFAULT NULL, 
    `created_at` datetime NOT NULL, 
    `updated_at` datetime NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `UNIQ_A0D153795E237E06` (`name`), 
    UNIQUE KEY `UNIQ_A0D1537961587F41` (`iso`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

と言語表のデータ:

id name  iso 
---------------------- 
1  English  en 
2  German  de 
3  Italian  it 

と国テーブル:

id code 
---------------- 
1  ie 

と国の言語テーブル

id country_id language_id name 
---------------------------------------------- 
1  1    1    Ireland in English 
2  1    2    Ireland in German 

私はそれを表示できるように次の結果を返すクエリを作成しようとしています。デフォルト言語としての英語とid 3(イタリア)と言語のコンテンツが存在しない場合、デフォルトはにフォールバックする必要があり、たとえば設定することが可能である場合

(Language)   (Country name) 
English    Ireland in English 
German    Ireland in German 
Italian    #NULL OR EMPTY STRING 

そして第二に(可能ならば)私は理解しようとしていますここで

(Language)   (Country name) 
English    Ireland in English 
German    Ireland in German 
Italian    Ireland in English #please note language id is 3 -> Italian. 
+0

あなたの例では混乱しています。 "country languages table"は、実際にはテーブルか、クエリの結果ですか?また、クエリの直後には、 "id"が何を意味するのか、それらのデータがどのように集まっているのかはっきりしていません。 – Jakumi

+1

@Jakumi私は自分の質問を更新しました。私は今それがより明確であることを望む –

答えて

1

大丈夫なので、サブクエリを使わずに次のクエリを実行することもできます。私は、クエリオプティマイザがこれを行うと信じていますが、私はあまり確かではありません。

SELECT l.name as language, 
     (SELECT cl.name 
     FROM country_languages cl 
     WHERE cl.country_id=[the wanted country id] 
     ORDER BY cl.language_id=l.id DESC, 
       cl.language_id=1 DESC 
     LIMIT 1) as country_name 
FROM languages l 

このバージョンでは、language_id 1が優先されるフォールバックとして使用されていますが、同様の方法でさらに多くの言語を追加できます。代わりにFIND_IN_SETを2次基準として使用すると(FIND_IN_SET(cl.language_id,'1,2,3') DESCまたは好きな順番どおりに)動作します。

もちろんこのクエリは固定されたcountry_idです。参加する他に、複数の国のために同様の方法で拡張することができます

SELECT l.name as language, 
     (SELECT cl.name 
     FROM country_languages cl 
     WHERE cl.country_id=c.id 
     ORDER BY cl.language_id=l.id DESC, 
       cl.language_id=1 DESC 
     LIMIT 1) as country_name 
FROM countries c 
JOIN languages l 

サブクエリの代わりに二回country_languagesに参加すること、そしてちょうど最初のものはヌルされていない選択することになる(おそらくの一つでありますクリーナーソリューション):

SELECT l.name as language, 
     COALESCE(first.name, second.name) as country_name 
FROM countries c 
JOIN languages l 
LEFT JOIN country_languages first ON 
     (first.country_id=c.id AND first.language_id=l.id) 
LEFT JOIN country_languages second ON 
     (second.country_id=c.id AND second.language_id=1) 

言語ID 1がフォールバック言語の場合は、これは複数のフォールバック言語を提供するために拡張することもできます...

+0

コメントありがとう。デフォルト値はすべての国ではないはずであることに気が付かなかった... –

+1

1コメント。 'IFNULL'の代わりに' Symfony'と 'Doctrine'を使うので、' COALESCE'を使うべきです。 'IFNULL'の場合、' DoctrineExtension'クラスを書くべきです。 –

-1

を使用して最初の部分のためのクエリで結合します:

SELECT `country_languages`.id, `country_languages`.country_id,`country_languages`.language_id, `country_languages`.name FROM `countries` left join country_languages on `countries`.id=`country_languages`.`country_id` 

をあなたは国の言語テーブルの状態列を宣言し、0,1のようにステータスを設定することができ、このような結果として、それらがどのようにフェッチされるかについての優先度をマークするために2を指定します。

関連する問題