2010-05-27 19 views
1

Voici un exemple. Supposons que nous essayons de calculer des frais de service.Existe-t-il une conception de table SQL standard pour remplacer les valeurs par défaut de "grande image" avec des détails de niveau inférieur?

ventes Say aux Etats-Unis attirent une charge de 10 dollars, les ventes au Royaume-Uni attirent une charge de 20 dollars

Jusqu'à présent, il est facile - nous commençons à imaginer un tableau qui répertorie les charges par pays.

permet maintenant supposer que l'Alaska et Hawaï sont traités comme des cas particuliers, ils sont les deux rangées de 15 dollars

qui suggère une table avec les États, l'Alaska et Hawaï sont rechargées en 15, mais nous avons besoin probablement 48 (redondants) tous dire 10. Cela nous donne un problème de maintenance, notre utilisateur veut seulement taper 10 une fois pas 48 fois. Cela ne va pas non plus avec le Royaume-Uni. Le Royaume-Uni n'a pas d'états. Supposons que nous appliquions deux autres règles de coupe croisée.

Si vous commandez par téléphone il y a un supplément de 10% sur la charge. Si vous commandez via le web il y a une réduction de 10%.

Mais pour une raison que les propriétaires de l'entreprise connaissent mieux, le supplément/rabais sur Internet n'est pas appliqué à Hawaï.

Il me semble que c'est un problème assez courant et qu'il y a probablement une disposition bien connue des tables pour stocker les données. La plupart des cas sont traités par des réponses générales, mais il existe des variations de niveau très détaillées. Ils donnent naissance à un grand nombre de combinaisons théoriques, dont la plupart ne sont pas utilisées.

Répondre

1

Vous pouvez regrouper les états/pays en catégories et attribuer les frais aux catégories non aux États/pays.

+0

vous devez faire abstraction de l'entité facturable dans les catégories de facturation. alors vous pouvez minimiser le nombre de catégories, en même temps vous permettez la flexibilité dans combien et quelles entités vont à quelles catégories. – Randy

0

Alaska et Hawaï sont facturés à 15, mais sans doute nous avons besoin de 48 (redondant) lignes tout en disant 10.

Non, vous avez besoin de trois lignes: deux pour l'Alaska et Hawaï, et un pour les États-Unis continentaux.

Toutes les autres règles semblent être additives. Il y a un enregistrement dans une table pour chaque règle. Si la règle n'est pas déclenchée/correspondue, la charge n'est pas ajoutée.

+1

Je peux voir votre raisonnement pour trois lignes, et il stocke les données bien. Comment pouvons-nous interroger ... mon application vient avec dire 'CA' comme état et ne trouve aucune ligne. Pas trop d'un problème, je fais probablement une autre requête pour les États-Unis continentaux. Cela ne s'étend pas bien. Si le prochain cas particulier est Birmingham UK. Ça commence à être plus dur. Les règles ne sont pas toutes additives. Par exemple ... Le supplément web/téléphone ne s'applique pas à Hawaii. – RichardHowells

0

Une réponse:

create table charge(entity char(2) , amount int) ; 

insert into charge(entity, amount) ('DF', 10) ; -- defualt; 
insert into charge(entity, amount) ('AK', 15) ; -- alaska; 
insert into charge(entity, amount) ('HI', 15) ; -- hiwaii; 

Puis:

select coalesce(amount,(select amount from charge where entity = 'DF')) 
from charge where entity = 'DC'; 

vous obtenez le montant par défaut.

alternativement:

select amount 
from charge 
where entity 
    = (select coalesce(entity, 'DF') from charge where entity = 'DC'); 

En d'autres termes, utiliser un résultat nul et confluer pour remplacerons donnent aucun résultat avec un résultat par défaut, ou pour remplacer une entité non cotée avec une entité par défaut.


Voulez-vous une technique générale/idiome, ou une conception détaillée pour un cas particulier? C'est un idiome général.

Si c'est un cas spécifique, regardez ce que Robert Harvey a dit: "Toutes les autres règles semblent être additives.". Si oui, votre conception devient très simple, un tableau des frais, ou (mieux) un tableau des frais, un tableau des compétences, et une relation plusieurs-à-plusieurs. Encore une fois, cela ne fonctionne que dans un cas additif;

create table surcharges (id int not null primary key, 
    description varchar(50) not null, amount int) ; 

create table jurisdiction (id int not null primary key, 
    name varchar(50) not null, abbr char(5)); 

create table jurisdiction_surcharge (id int not null primary key, 
    jurisdiction_id int not null references jurisdiction(id), 
    surcharge_id int not null references surcharge(id)); 

insert into charges (description, amount) values ('Outside Continental US', 15); 

insert into jurisdiction (name, abbr) values ('Mainland US', 'CONUS'); 
insert into jurisdiction (name, abbr) values ('Alaska', 'AK'); 
insert into jurisdiction (name, abbr) values ('Hawaii', 'HI'); 

insert into jurisdiction_surcharge 
values (jurisdiction_id, surcharge_id) values (2, 1); 
insert into jurisdiction_surcharge 
values (jurisdiction_id, surcharge_id) values (3, 1); 

Liste Charges:

select a.* 
from charges a 
join jurisdiction_charge b on (a.id = b.surcharge_id) 
join jurisdiction c on (c.id = b.jurisdiction_id) 
where c.abbr='AK'; 

Charges Somme:

select sum(a.amount) 
from charges a 
join jurisdiction_charge b on (a.id = b.surcharge_id) 
join jurisdiction c on (c.id = b.jurisdiction_id) 
where c.abbr='AK'; 
+0

C'est une technique soignée et ça marche bien quand il n'y a que deux niveaux; un défaut global plus des exceptions. Dans ce cas, il laisse tout le Royaume-Uni sur 20 et j'ai toujours besoin d'idées sur la manipulation de la surtaxe/réduction. – RichardHowells

0

Je serais enclin à permettre à des moyens multiples pour identifier la zone où une charge de service donné appliqué comme ceci:

Create Table ServiceCharges 
    (
    Country char(3) not null    -- ISO 3166-2 alpha-3 code 
    , StateOrProvince nvarchar(25) null  -- ideally a code but given multiple 
              -- countries, that may not be feasible 
    , City nvarchar(128) null    -- again name 
    , PostalCode varchar(10) null      
    , Rate decimal(16,4) not null    
    , Constraint CK_ServiceCharges_RateGTEZero Check (Rate >= 0) 
    , Constraint CK_ServiceCharges_MinEntry Check (Case 
                When Country Is Null 
                 And StateOrProvince Is Null 
                 And City Is Null 
                 And PostalCode Is Null Then 0 
                 Else 1 
                 End = 1) 
) 

Cela pourrait aussi être divisé à part pour que les emplacements sont maintenus dans une table séparée avec une colonne de substitution LocationId appliquée dans la table ServiceCharges. Cette conception ne tient pas compte du chevauchement qui amène à la question: que devrait-il se passer en cas de chevauchement? Que se passe-t-il si les États-Unis ont une charge, mais que TX en a une autre? Est-ce que le taux TX atout? Si tel est le cas, cela signifie que l'emplacement le plus spécifique gagne et nous pouvons déterminer la spécificité par l'existence d'un code postal ou d'une ville ou d'une province ou d'une province ou d'un pays.