2010-12-13 44 views
1

J'ai une simple table customers conçu de cette façon (je signale que certains domaines, ceux concernant cette qeustions):SQL: conception de table pour navire/adresse de facturation et numéro SELECT CONCAT

+ ----------- + --------------- + ---------------- + 
+ customer_id + invoice_address + ship_address  + 
+ ----------- + --------------- + ---------------- + 
+ 33   + 234, Walnut Ave + null    + 
+ ----------- + --------------- + ---------------- + 
+ 47   + 66, Smart Ave + null    + 
+ ----------- + --------------- + ---------------- + 
+ 47   + 4, Cool Ave  + 45, Dark Street + 
+ ----------- + --------------- + ---------------- + 

Lignes avec null ship_address signifie que nous devons utiliser l'adresse de facturation du client également pour l'expédition.


1ère question: est ce assez bon design, ou si tous les champs nullship_address être rempli avec l'adresse de facturation (même si identique) et non null gauche.

2ème question: garder une telle conception (même dans le cas où il est une mauvaise conception), comment puis-je créer une requête SELECT (si possible) qui retourne toujours une adresse unique pour chaque ligne: le ship_address quand ne pas null, sinon juste le invoice_address, quelque chose comme:

SELECT CONCAT_IF_SHIP_ADDRESS_NOT_NULL_OTHERWISE_USE_ONLY_SHIP_ADDRESS(invoice_address, ship_address) AS address FROM customers; 

requête pour MySQL DB.

Merci,

Répondre

2

Vous avez un 1-à-plusieurs entre les clients et les adresses, donc je tirer à répondre dans une table séparée avec un « type » pour les distinguer . Je considérerais casser l'adresse elle-même en attributs séparés. En option, vous pouvez même ajouter des tables de référence pour les villes/états/pays valides.

alt text

En ce qui concerne l'interrogation des données dans cette structure, en supposant 1 adresse existe toujours et vous créer des enregistrements de addresstype dans l'ordre souhaité (par exemple, facture = 1, Expédition = 2):

select c.CustomerID, a.AddressLine1, a.AddressLine2, a.AddressLine3, 
     a.City, a.State, a.PostalCode, a.Country 
    from Customer c 
     inner join (select MIN(cax.AddressTypeID) as MinAddressTypeID 
         from CustomerAddressXref cax 
         where cax.CustomerID = c.CustomerID 
         group by cax.CustomerID) mincax 
     inner join CustomerAddressXref cax 
      on c.CustomerID = cax.CustomerID 
       and mincax.MinAddressTypeID = cax.AddressTypeID 
     inner join Address a 
      on cax.AddressID = a.AddressID 
+0

Eh bien, ce sont les types de réponses qui font vraiment un endroit unique pour apprendre. Cette conception est géniale, le seul effet secondaire est qu'un simple SELECT sur le client (avec l'adresse) exigera toujours un JOIN. Mais pour prodcution et impatience quand la DB pourrait devenir énorme c'est certainement le bon chemin à parcourir. –

+0

En fait, Customer - Address est une relation an n: m parce que la même adresse peut être pour plusieurs clients (ie différents employés dans la même entreprise, j'utilise la même adresse de compagnie que l 'adresse de livraison). la table peut gérer cela aussi. BTW: J'avais déjà divisé la Ville, l'État, .. Fileds, je ne les ai pas écrits dans la question afin de garder les choses simples. –

+0

que se passe-t-il si le client change d'adresse? Les adresses de facturation précédentes du client ne devraient pas changer à des fins historiques ... que devrait-on faire alors? – greaterKing

2

Je pense que le schéma est bon. si vous utilisez ms sql server vous pouvez utiliser soudent, comme ceci:

select coalesce(ship_address,invoice_address) as address 
from customers 

soudent prend essentiellement une liste d'éléments, et affiche le premier élément de la liste qui est non nulle.

+1

Ça fonctionne super bien! COALESE est aussi en MySQL. –

+0

Votre réponse s'adapte très bien à ma question et fonctionne, +1. Je choisis la réponse de Joe Stefanelli parce que ça marche aussi et c'est plus complet et répond bien aussi à ma 1ère question. –

1

Cela fera

SELECT customer_id, ISNULL(ship_address,invoice_address) AS address 
FROM customers 
+0

Cette réponse est totalement fausse. –

+0

Oh, je vois que vous cherchiez la requête dans MySQL? J'imagine voir la balise MySQL initialement, je pensais que c'était pour MS SQl .Im MS SQL ISNULL fonction est utilisée pour définir une valeur de remplacement si la valeur d'expression (vaule sur le côté gauche) est NULL, ie dans votre cas si ship_address est nulle alors renvoie la valeur de invoice_address.Et dans MySQL, la fonction ISNULL est pour la vérification de la valeur NULL, n'est-ce pas? – wizzardz

1

Vous devriez laisser l'adresse du navire null comme la copie de l'adresse de facturation conduira à la redondance.

Quant à la requête:

SELECT invoice_address 
from table 
where ship_address IS Null 

UNION 

SELECT ship_address 
from table 
where ship_address IS NOT NULL 
+0

si ship_address est null, il suffit de lire la facture – Programmer

+0

exactement ce que fait 'ISNULL'. – wizzardz