Autor Beitrag
Yogu
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2598
Erhaltene Danke: 156

Ubuntu 13.04, Win 7
C# (VS 2013)
BeitragVerfasst: Do 08.04.10 12:00 
Moin,

ich habe eine multilinguale Webseite, bei der aber nicht unbedingt alle Inhalte in alle Sprachen übersetzt sein müssen. Wenn eine Übersetzung fehlt, soll zuerst die in die als international deklariere Sprache Übersetzung, dann irgendeine andere ausgewählt werden.

Die Inhalte sind in einer Tabelle namens strings (jeder String hat eine ID) aufgelistet, die Übersetzungen in translations, die die String-ID und eine Sprach-ID enthält.

Da ich alle Strings haben möchte, verwende ich zuerst folgende Query:

ausblenden SQL-Anweisung
1:
2:
SELECT strings.id
FROM strings

Um nun an die Übersetzungen zu kommen, verwende ich derzeit eine Subquery:

ausblenden SQL-Anweisung
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
SELECT strings.id, (
  SELECT translations.value
  FROM translations
  WHERE strings.id = translation.stringID
  ORDER BY
    translation.languageID = 3 DESC,
    translation.languageID = 2 DESC
  LIMIT 0,1
AS value
FROM strings

Wobei languageID 3 die aktive Sprache und 2 die internationale ist.

Da dieses Schema aber sehr häufig vorkommt, möchte ich von einer Subquery absehen und das ganze lieber mit JOINS realisieren. Ein Ansatz dafür ist:

ausblenden SQL-Anweisung
1:
2:
3:
4:
5:
6:
7:
SELECT strings.id, translations.value
FROM strings
LEFT JOIN translations
  ON translations.stringID = strings.id
ORDER BY
  translation.languageID = 3 DESC,
  translation.languageID = 2 DESC

Jetzt muss ich nur noch doppelte Strings entfernen. Weiß jemand, wie das in diesem Fall geht? DISTINCT funktioniert nur, wenn ich translation.value aus der SELECT-Klausel entferne - und die Spalte brauche ich natürlich unbedingt.

GROUP BY wäre auch noch eine Idee, aber das entfernt doppelte Strings aus, bevor nach Sprache sortiert wird, und dann wird per Zufall entschieden, welche Sprache ausgewählt wird.

Danke für eure Mühe!

Grüße,
Yogu
Yogu Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2598
Erhaltene Danke: 156

Ubuntu 13.04, Win 7
C# (VS 2013)
BeitragVerfasst: Sa 10.04.10 15:27 
*push*
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Sa 10.04.10 17:26 
user profile iconYogu hat folgendes geschrieben Zum zitierten Posting springen:
Moin,

ich habe eine multilinguale Webseite, bei der aber nicht unbedingt alle Inhalte in alle Sprachen übersetzt sein müssen. Wenn eine Übersetzung fehlt, soll zuerst die in die als international deklariere Sprache Übersetzung, dann irgendeine andere ausgewählt werden.

Die Inhalte sind in einer Tabelle namens strings (jeder String hat eine ID) aufgelistet, die Übersetzungen in translations, die die String-ID und eine Sprach-ID enthält.

Gibt es eine weitere Tabelle mit der Vorzugsreihenfolge der Sprachen? Wenn ja, könnte man da glaube was mit GROUP BY + HAVING\MAX\MIN machen.

Müsste das aber auch erst raussuchen.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Yogu Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2598
Erhaltene Danke: 156

Ubuntu 13.04, Win 7
C# (VS 2013)
BeitragVerfasst: Sa 10.04.10 20:32 
Hallo,

danke für den Tipp mit MAX, vielleicht bin ich jetzt einen Schritt weiter.

Folgende Abfrage gibt mir zwar immer noch eine willkürliche Übersetzung zurück, aber wenigstens wird schon mal markiert, wie richtig die Sprache sein kann (also wie nah die beste Übersetzung an den Benutzerwunsch hinkommt), und dann noch, wie richtig die der tatsächlich gewählten Übersetzung ist:

ausblenden SQL-Anweisung
1:
2:
3:
4:
5:
SELECT strings.id, translations.value, translations.languageID, MAX(CASE translations.languageID WHEN 3 THEN 2 WHEN 2 THEN 1 ELSE 0 ENDAS möglicheQualität, (CASE translations.languageID WHEN 3 THEN 2 WHEN 2 THEN 1 ELSE 0 ENDAS tatsächlicheQualität
FROM strings
LEFT JOIN translations
  ON strings.id = translations.stringID
GROUP BY strings.id

Meine Idee war nun, die tatsächliche mit der möglichen Qualität in einer HAVING-Klausel gleichzusetzen.

Das hier:
ausblenden SQL-Anweisung
1:
2:
3:
4:
5:
6:
SELECT strings.id, translations.value, translations.languageID, MAX(CASE translations.languageID WHEN 3 THEN 2 WHEN 2 THEN 1 ELSE 0 ENDAS möglicheQualität, (CASE translations.languageID WHEN 3 THEN 2 WHEN 2 THEN 1 ELSE 0 ENDAS tatsächlicheQualität
FROM strings
LEFT JOIN translations
  ON strings.id = translations.stringID
GROUP BY strings.id
HAVING tatsächlicheQualität = möglicheQualität

gibt aber einfach nur die Strings aus, bei denen die Übersetzung zufällig passt, und die anderen werden gar nicht ausgegeben.

Das Problem könnte ich wiederum mit einer Subquery lösen:

ausblenden SQL-Anweisung
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
SELECT strings1.id, translation.value, translation.languageID
FROM strings AS strings1
LEFT JOIN translations AS translations1
  ON strings1.id = translations1.stringID
WHERE
  (CASE translation1.languageID WHEN 3 THEN 2 WHEN 2 THEN 1 ELSE 0 END) = (
    SELECT MAX(CASE translation2.languageID WHEN 3 THEN 2 WHEN 2 THEN 1 ELSE 0 END
    FROM strings AS strings2
    LEFT JOIN translations AS translations2
      ON strings2.id = translations2.stringID
    WHERE string1.id = strings2.id
  )

Womit ich wieder am Anfang wäre: Bei einer Subquery, die wertvolle Zeit verbraucht.

Hat jemand eine Idee, wie ich ohne Subquery auf den Maximalen Wert der Case-Anweisung
ausblenden SQL-Anweisung
1:
CASE translations.languageID WHEN 3 THEN 2 WHEN 2 THEN 1 ELSE 0 END					

komme?

Danke!

Grüße,
Yogu