2016-08-30 3 views
2

ich eine Datenbankstruktur wie dieses:mysql Übersetzungstabellen mit fehlenden Sprachausweich

Länder

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; 

Länder Sprache

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; 

Sprache

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; 

und die Daten für die Tabelle Sprachen:

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

Und Land Tabelle:

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

und Tisch Land Sprachen

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

Ich versuche eine Abfrage zu schreiben, die das folgende Ergebnis zurückgibt, um es anzuzeigen. (Wenn möglich)

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

Und zweitens Ich versuche zu verstehen, wenn es möglich ist, Englisch als Standardsprache zum Beispiel zu setzen und, wenn Inhalte für die Sprache mit der ID 3 (Italienisch) nicht vorhanden ist sollte der Standardrückfall in als Ergebnis wie folgt aus:

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

Ich bin verwirrt von Ihrem Beispiel. die "country languages ​​table", ist das eigentlich eine Tabelle oder ist das Ergebnis einer Abfrage? Auch die Abfragen direkt danach, es ist einfach nicht klar was "id" bedeuten soll und wie diese Daten zusammen kommen ... – Jakumi

+1

@Jakumi Ich habe meine Frage aktualisiert. Ich hoffe jetzt ist es klarer –

Antwort

1

okay, so kann die folgende Abfrage wahrscheinlich ohne eine Unterabfrage aber mit einem Join statt. Ich würde darauf vertrauen, dass der Abfrageoptimierer dies tut, aber ich wäre mir nicht sicher.

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 

In dieser Version language_id 1 als bevorzugte Ausweichlösung verwendet wird, könnten Sie wahrscheinlich mehr Sprachen in ähnlicher Weise hinzuzufügen. Die Verwendung von FIND_IN_SET stattdessen als Kriterium zweiter Ordnung würde ebenfalls funktionieren (FIND_IN_SET(cl.language_id,'1,2,3') DESC oder welche Reihenfolge Sie bevorzugen).

Natürlich ist diese Abfrage jetzt für eine feste country_id. Es könnte mit einem anderen in ähnlicher Weise für mehrere Länder ausgedehnt wird beitreten:

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 

eine Alternative zu Unterabfragen des country_languages ​​zweimal zu verbinden wäre, und wählen Sie nur die erste nicht null ist (was wahrscheinlich eine die ist Reinigerlösungen):

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) 

Wenn Sprache 1 Ihre Ausweichsprache ist. Dies kann erweitert werden, um mehrere Fallback-Sprachen zur Verfügung zu stellen ...

+0

Danke für den Kommentar. Habe nicht bemerkt, dass der Standardwert nicht für alle Länder gelten sollte ... –

+1

Ein Kommentar. Da ich "Symfony" und "Doctrine" anstelle von "IFNULL" verwende, sollte 'COALESCE' verwendet werden. Für die IFNULL sollten Leute eine 'DoctrineExtension' Klasse schreiben. –

-1

Hier ist die Abfrage für den ersten Teil Joins:

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` 

Sie können eine Statusspalte in Ländern Sprachen Tabelle und stellen Sie den Status als 0,1 deklarieren , 2 um Prioritäten zu setzen, wie sie geholt werden.