Autor | Zpráva | ||
---|---|---|---|
polonium Profil |
#1 · Zasláno: 1. 2. 2013, 21:23:47
Ahojte,
řeším menší dilema. Řekněme, že mám v databázi tabulku v níž jsou uloženy objednávky. Každá objednávka má ve sloupečcích info o způsobu dopravy, jeho ceně a sazbě DPH (postageId, postageTax, postagePrice). Protože je jasné, že časem se může DPH změnit nebo cena dopravy, ale zárovneň potřebuju zachovat její hodnotu v uložené objednávce. Jelikož se cena a DPH mění jen jednou za dlouhou dobu v tabulce se tak objevuje spousta duplicitních záznamů. Řeším tedy dilema jestli má smysl vytvořit novou tabulku kde by byly duplicity sjednoceny nebo to prostě nechat být. Co myslíte? |
||
Taps Profil |
#2 · Zasláno: 1. 2. 2013, 21:57:05
polonium:
a nebylo by vhodné tuto problematiku vyřešit pomocí triggeru ? |
||
polonium Profil |
#3 · Zasláno: 1. 2. 2013, 22:04:46
Možná úplně nechápu jak
|
||
juriad Profil |
#4 · Zasláno: 1. 2. 2013, 22:08:12 · Upravil/a: juriad
Ke každému záznamu, ketrý se může měnit přidej sloupce platnost_od a platnost_do.
Mezi produkty budeš používat vždy aktuálně platný záznam, ve faktuře ten, který byl platný v době jejího vystavení. Budeš tedy mít tabulky produkty (id, název, popis, dph_id) ceny_produktu (produkt_id, cena, platnost_od, platnost_do) faktury (id, dph_id, doprava_id, cas_vystaveni) produkty_ve_fakture (faktura_id, produkt_id, pocet) dph (id, hodnota, platnost_od, platnost_do) doprava (id, popis, hodnota, poatnost_od, platnost_do) Výpis všech produktů s cenami: SELECT p.*, c.cena, c.cena*(1+d.hodnota) FROM produkty p JOIN ceny_produktu c ON p.id = c.produkt_id AND NOW() BETWEEN c.platnost_od AND c.platnost_do JOIN dph d ON p.dph_id = d.id AND NOW() BETWEEN d.platnost_od AND d.platnost_do SELECT p.*, f.pocet, c.cena, c.cena*(1+d.hodnota) FROM faktury f JOIN produkty_ve_fakture pf ON f.id = pf.faktura_id JOIN produkty p ON pf.produkt_id = p.id JOIN ceny_produktu c ON p.id = c.produkt_id AND f.cas_vystaveni BETWEEN c.platnost_od AND c.platnost_do JOIN dph d ON p.dph_id = d.id AND f.cas_vystaveni BETWEEN d.platnost_od AND d.platnost_do WHERE f.id = ID_FAKTURY |
||
polonium Profil |
#5 · Zasláno: 1. 2. 2013, 22:57:33
A když je cena_produktu právě platná znamená to, že hodnota platnost_do bude mít hodnotu NULL? BETWEEN si s tím dokáže poradit jako kdyby NULL = NOW()?
|
||
juriad Profil |
#6 · Zasláno: 2. 2. 2013, 10:45:00
NULL ti s between podle dokumentace fungovat nebude, ale nic ti nebrání nahradit BETWEEN za porovnání:
NOW() >= platnost_od AND (NOW() < platnost_do OR platnost_do IN NULL) Nicméně, aktualizaci ceny bude nejlepší stejně provádět TRIGGEREM, jak navrhuje Taps, píšu od boku: CREATE TRIGGER nastavPlatnost BEFORE INSERT ON ceny_produktu # bude se provadet automaticky pred kazdym insertem do tabulky ceny_produktu FOR EACH ROW BEGIN # NEW se odkazuje na vkládaný záznam, hodnotu, kterou predáváš v INSERTU UPDATE ceny_produktu SET platnost_do = NOW() WHERE produkt_id = NEW.produkt_id AND platnost_do = NULL; # ukonci platnost aktualniho SET NEW.platnost_od = NOW(); # nastavi zacatek platnosti vkladaneho END; INSERT INTO ceny_produktu (produkt_id, cena) VALUES (123, 456) |
||
polonium Profil |
#7 · Zasláno: 2. 2. 2013, 12:03:35
Jo, to je dobré řešení :)
Možná se to, ale trochu komplikuje ve chvíli, kdy se rozhodnu změnit cenu produktu v objednávce. V takovém případě už tohle asi fungovat nebude moc elegantně, musel bych vložit do tabulky ceny_produktu dva nové řádky a upravit časy platností na 3 řádcích. Nebo to udělat elegantněji, že tu úpravu ceny v objednávce bych realizoval formou slevy: slevy_produktu_v_objednavce (objednavka_id, produkt_id, sleva) |
||
Časová prodleva: 17 dní
|
|||
polonium Profil |
#8 · Zasláno: 19. 2. 2013, 10:35:58
juriad:
Tak jsem ten trigger zkoušel a výsledkem byla chyba 1442, tuším, že to souvisí s tím UPDATE :( |
||
juriad Profil |
#9 · Zasláno: 19. 2. 2013, 11:04:07
Aha, jedná se o omezení mysql; databáze sqlite, se kterou jsem pracoval toto omezení neměla. Za zmatení se omlouvám.
V tom případě ti nezbývá než provést úlohu TRIGGERU manuálně v php: $produkt_id = 123; $cena = 456; $now = date("Y-m-d H:i:s"); $end_previous = "UPDATE ceny_produktu SET platnost_do = '$now' WHERE produkt_id = $produkt_id AND platnost_do = NULL" mysql_query($end_previous); $add_new = "INSERT INTO ceny_produktu (produkt_id, cena, platnost_od) VALUES ($produkt_id, $cena, '$now')"; mysql_query($add_new); |
||
polonium Profil |
#10 · Zasláno: 19. 2. 2013, 11:12:41
Ok, děkuju ti :) A ještě drobnost, myslíš, že toto omezení se týká i třeba PostgreSQL?
|
||
juriad Profil |
#11 · Zasláno: 19. 2. 2013, 12:30:58
Podle dokumentace to vypadá, že takové omezení tam není:
for example, an INSERT trigger might execute a command that inserts an additional row into the same table |
||
Časová prodleva: 11 let
|
0