WN

WN (https://www.wn.se/forum/index.php)
-   Serversidans teknologier (https://www.wn.se/forum/forumdisplay.php?f=4)
-   -   En fråga om SQL-satser (https://www.wn.se/forum/showthread.php?t=9039)

koala 2005-07-24 14:32

Jag har en tabell som heter category, med fält category_id, language_id, category_name. Det är tänkt att jag ska hämta en kategoris namn beroende på vilket språk användaren har valt. Nu vill jag dock att standardspråket (1) ska användas ifall det valda språket (2) råkar sakna översättning.

Funderade på om det går att göra på ett smidigare sätt än som som jag gör nu (en aning förkortad kod nedan för överskådlighetens skull):

Kod:

// Standardspråket
$query = "SELECT category_id, category_name FROM category WHERE language_id=1";
$result = mysql_query($query);
while ($o = mysql_fetch_object($result)) {
        $categories[$o->category_id]->category_name = $o->category_name;
}
mysql_free_result($result);

// Översättning till annat språk som användaren råkar ha valt (språket har t ex id 2)
$query = "SELECT category_id, category_name FROM category WHERE language_id=2";
$result = mysql_query($query);
while ($o = mysql_fetch_object($result)) {
        if (!empty($o->category_name)) {
 $categories[$o->category_id]->category_name = $o->category_name;
        }
}
mysql_free_result($result);

Det känns som att det går att åstadkomma det jag önskar med en smartare SQL-sats. Eller har jag fel? Något tips på smartare sätt att göra, eller är det inga större fel på min kod ovan?

koala 2005-07-24 14:49

Kom på ett alternativt sätt. Följande är åtminstone snyggare att se på:
Kod:

$query = sprintf("SELECT category_id, category_name FROM %s WHERE language_id=%d OR language_id=%d ORDER BY language_id ASC",
          $DBTABLES['shop']['category_description'],
          DEFAULT_LANGUAGE,
          $user->language_id
  );
$result = mysql_query($query);
while ($o = mysql_fetch_object($result)) {
        if (!empty($o->category_name)) {
 $categories[$o->category_id]->category_name = $o->category_name;
        }
}
mysql_free_result($result);

Finns det bättre lösningar?

EDIT: Det här fungerar inte om DEFAULT_LANGUAGE > $user->language_id. Måste komma på något smartare.

EDIT2: Det här fungerar nog alltid:
Kod:

// Category descriptions:
$query = sprintf("(SELECT category_id, category_name FROM %s WHERE language_id=%d) UNION (SELECT category_id, category_name FROM %s WHERE language_id=%d)",
          $DBTABLES['shop']['category_description'],
          DEFAULT_LANGUAGE,
          $DBTABLES['shop']['category_description'],
          $user->language_id
  );
$result = mysql_query($query) or trigger_error(sprintf("(%d)\n%s\nWhole query:\n%s", mysql_errno(), mysql_error(), $query), E_USER_ERROR);
while ($o = mysql_fetch_object($result)) {
        $categories[$o->category_id]->category_name = $o->category_name;
}
mysql_free_result($result);

Är det en bra lösning?

eg0master 2005-07-24 21:35

Citat:

Originally posted by koala@Jul 24 2005, 14:49
Är det en bra lösning?
Bra?, nja. Snygg? Nej.

Du kommer ju loopa över dubbelt så många poster som du behöver.

Kod:

$query = sprintf("SELECT cd.category_id, cd.category_name, mc.category_name FROM %s AS cd LEFT OUTER JOIN %s AS mc ON cd.category_id=mc.category_id WHERE cd.language_id=%d AND mc.language_id=%d",
  $DBTABLES['shop']['category_description'],
  $DBTABLES['shop']['category_description'],
  DEFAULT_LANGUAGE,
  $user->language_id
  );

Du får ett resultat med både default språk och valt språk på samma rad. Bara att kolla om valt språk är NULL eller inte när du ska fylla på din array.

koala 2005-07-25 08:40

Det var precis något sådant jag ville åstadkomma eg0master. Ett problem återstår dock när jag provar med ditt förslag: Bara de fält som har översättning kommer med i resultset. Alltså, min tabell ser ut så här:

Kod:

category_id | language_id | category_name
-------------------------------------------------------
1 | 1 | Svenskt namn
1 | 2 | Norskt namn
2 | 1 | Svenskt namn
3 | 1 | Svenskt namn
4 | 1 | Svenskt namn

Och med ditt förslag kommer endast category_id 1 att finnas med i resultset. Väljer jag OR istället för AND så kommer dock alla med, men då blir det återigen dubbla antalet poster som kommer med.

EDIT: Sorry, jag är bara lite morgontrött ;)

Det är ju bara att se till att default language hamnar i vänstra tabellen...
Jag får tacka så mycket för din hjälp eg0master!

koala 2005-07-25 09:31

För den intresserade ser min SQL-sats nu ut som följer, och resultatet är det önskade.

Citat:

SELECT cd.category_id, cd.category_name as cnDef, mc.category_name as cnPref FROM shop_category_description AS cd
LEFT JOIN shop_category_description AS mc
ON cd.category_id=mc.category_id AND cd.language_id!=mc.language_id
WHERE cd.language_id=1 OR mc.language_id=2



Alla tider är GMT +2. Klockan är nu 14:20.

Programvara från: vBulletin® Version 3.8.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Svensk översättning av: Anders Pettersson