2010-09-13 16 views
0

Je travaille sur une webapp avec un ensemble de données que les utilisateurs peuvent parcourir et modifier.Choisir une colonne avec une valeur par défaut ou une colonne avec une valeur définie par l'utilisateur sinon null?

Les utilisateurs veulent personnaliser l'un des champs qui apparaissent pour chaque élément, par exemple "product_name".

Chaque produit a un ensemble de valeurs par défaut dans une table, qui est la même pour tous les utilisateurs:

Le tableau des produits serait comme (sauter cruft syntaxe, vous voyez l'idée):

CREATE TABLE products (
    pid  int,   # product id 
    pname varchar   # product name (users want to customize this) 
); 

Je dois afficher le nom du produit personnalisé de l'utilisateur dans toutes les tables/listes de mon site chaque fois qu'il y a une valeur personnalisée pour ce produit, mais sinon afficher la valeur par défaut.

Pour l'efficacité de l'espace, j'ai pensé à utiliser une table supplémentaire qui sorte de "remplacer" les valeurs par défaut, pour un utilisateur donné, pour un produit donné. Les lignes sont ajoutées dans cette table si nécessaire. Un utilisateur qui ne personnalisez un nom de produit ne serait pas toutes les lignes là:

CREATE TABLE custom (
    pid  int, 
    userid int, 
    pname varchar 
); 

je peux facilement joindre ces deux tableaux identifiant du produit, et pourrait prendre la valeur par défaut (products.pname), ou modifié par l'utilisateur value (custom.pname) pour chaque ligne de php, mais j'espère qu'il y a un moyen plus efficace de le faire en MySQL.

Existe-t-il une expression qui me permet de choisir une colonne si elle n'est pas nulle, sinon en choisir une autre (sur deux tables)?

Suggérez-vous une autre façon de gérer cela?

Merci. PS: peut-être un type de JOIN qui permettrait à une colonne de la table 2 du même nom de surcharger une colonne du tableau 1 pour les lignes où elle existe dans la table 2?

Répondre

1

Vous recherchez la fonction COALESCE.

SELECT COALESCE(the_field, "This literal") FROM YOUR_TABLE 

résulte dans the_field si the_field n'est pas nul, sinon c'est "This literal". Vous pouvez mélanger des champs et des littéraux autant que vous le souhaitez. SELECT SELECT COALESCE (this_field, that_field) fonctionne également. Vous pouvez avoir plus de 2 paramètres ... par ex. SELECT COALESCE (this_field, that_field, theother_field)

+0

Merci. J'ai trouvé un opérateur similaire appelé IFNULL(). IFNULL (expr1, expr2) semble être équivalent à COALESCE (expr1, expr2). Je ne suis pas sûr de l'utilité de cette variante car COALESCE() peut prendre plus de deux arguments. –

+1

@faB: IFNULL est spécifique à MySQL; 'COALESCE' est un standard ANSI et peut être utilisé sur différentes bases de données. Comme vous l'avez mentionné, 'COALESCE' peut aussi prendre plus de deux paramètres. La plupart recommandent d'utiliser la syntaxe ANSI autant que possible. –

1

Jetez un oeil à CASE-statement de MySQL. Cela devrait faire l'affaire:

SELECT CASE 
       WHEN `custom`.`pname` IS NULL 
       THEN `products`.`pname` 
       ELSE `custom`.`pname` 
      END CASE AS `pname` 
    FROM `products` 
LEFT JOIN `custom` 
     ON `custom`.`pid` = `products`.`pid` 
    WHERE `products`.`pid` = 123 

Je n'ai pas testé cela, mais c'est comme ça que ça devrait fonctionner.

+0

Merci, de toute façon de le faire avec une simple requête SELECT? Je n'ai pas encore utilisé de "programme stocké" (procédure stockée?) Sur cette application, et je n'ai pas encore de framework pour cela. –

+0

Jetez un oeil à mon ajout. – jwueller

+0

Merci d'avoir mis en évidence CASE dans une instruction SELECT. –

2

Utilisez une combinaison de LEFT JOIN et COALESCE:

SELECT p.pid, 
      COALESCE(c.pname, p.pname) AS product_name 
    FROM PRODUCT p 
LEFT JOIN CUSTOM c ON c.pid = p.pid 
        AND c.userid = ? 

Parce que c.pname sera nulle si l'utilisateur n'a pas fourni un nom personnalisé, la fonction COALESCE sera par défaut à utiliser la prochaine valeur non NULL - de p.pname.

2
select if(c.pname is not null, c.pname, p.pname) pname 
    from products p left outer join custom c on c.pid = p.pid; 

La jointure externe gauche offre toujours un match de suite, ce qui aura des champs nuls si la jointure échoue, vous pouvez vérifier que la fonction if().

+0

Ah, je pensais qu'il devait y avoir quelque chose comme un opérateur ternaire. Il sera intéressant de rechercher ceci et de fusionner maintenant dans le manuel de référence et de voir comment les approches diffèrent. Je vous remercie! –