Autor Zpráva
Prochy
Profil
Zdravím,

dneska mě dostihl po 6 letech chybný návrh databáze, kterou jsem navrhoval. Problém je následující:
Aplikace prodává jistý typ karet: např. CPP001, CPP0002 atd.
Pokaždé, když se prodává karta, tak najdu poslední kartu daného typu (např. CP), seřadím podle abecedy sestupně, zvýším o jednu a tak nastavím identifikátor pro kartu, kterou následně prodám.
Problém je, že identifikátor byl formátovaný na tři číslice, tj. 001-999 pomocí funkce sprintf. No a teď se dostali k číslu 1000, ale to už MySQL chybně seřadí, takže jako poslední kartu dostanu opět CP999 a db vyhodí error kvůli tomu, že sloupec má unique, což je správně.

Jak to nejlépe vyřešit? Určitě by bylo nejlepší, kdybych měl pouze sloupec s čísly, ale to je příliš velký zásah do databáze, takže nejlepší by bylo pouze upravit dotaz tak, aby to dokázalo řadit správně i s textem.

Aktuálně je SQL dotaz následující:
SELECT identificator FROM prepaid_products WHERE product=%i ORDER BY identificator DESC
Vymslel jsem takovýto dotaz:
SELECT identificator FROM prepaid_products WHERE product=%i ORDER BY cast(RIGHT(identificator,LENGTH(identificator)-3) as unsigned) DESC
Textový identifikátor je vždy 3 znaky dlouhý.
Případně ještě tenhle SQL dotaz:
SELECT identificator FROM prepaid_products WHERE product=%i ORDER BY cast(RIGHT(identificator,LENGTH(identificator)-(SELECT LENGTH(identificator) FROM list_products WHERE id=%i)) as unsigned) DESC
Tady vytáhnu z jiné tabulky délku identifikátoru (CPP=2), kdyby se do budoucna rozhodlo, že by identifikátor mohl mít i označení jiné, než na tři písmena.

Oba dotazy fungují, spíš by mě zajímalo, jestli bych to měl řešit jinak, pokud neberu překopání databáze.

Děkuji
Radek9
Profil
Prochy:
Ideální by bylo nechat generování ID přímo na DB. Tady se můžeš dostat do problémů i kvůli konkurentním dotazům. Pokud ale nechceš překopávat DB, tak můžeš použít ještě sestupné řazení podle délky identifikátoru:

SELECT identificator
FROM prepaid_products
WHERE product = %i
ORDER BY LENGTH(identificator) DESC, identificator DESC
LIMIT 1 -- v případě, že chceš opravdu jen ten poslední
Prochy
Profil
Ano, jsem si toho vědom, že nejlepší by bylo to rozdělí a nastavit to jako číslo, ale myslím, že nyní by to přineslo víc škod než užitku. Asi jsem to takhle udělal, aby mi databáze sama zahlasila, že tam je duplikat, jiný důvod nevidím.
Použiji tvoje řešení, vypadá o něco líp než to moje, a budu doufat, že se další problémy neobjeví. Jediný, co mě napadá, že to bude chybně řadit v určitých přehledech.
Radek9
Profil
Prochy:
Ano, jsem si toho vědom, že nejlepší by bylo to rozdělí a nastavit to jako číslo, ale myslím, že nyní by to přineslo víc škod než užitku.
Záleží, kde všude se s tou informací pracuje a jak moc je ta aplikace „naprasená“. :-) Obecně by měla stačit jedna migrace a pár změn při vytváření nové instance. Ale to bez dalších informací nedokážu posoudit.

Jediný, co mě napadá, že to bude chybně řadit v určitých přehledech.
Teď si nejsem úplně jistý, co tím myslíš.
Prochy
Profil
Právěže to byl můj první větší projekt a upřímně není to úplně moje nejlepší práce, proto se v tom nechci příliš šťourat.

V aplikaci jsou přehledy např. prodaných karet, kde pokud si to uživatel teď seřadi, tak to nebude fungovat stoprocentně správně. Ze na prvním místě nebude CP1000, ale CP999. Ale tohle beru jako nejmenší detail. Tvoje řešení se tady aplikovat určitě nedá, jelikož když bude mít uživatel více typů karet např. CP, CD, tak by mu to uprednostnilo CP1000 před CD800, pokud se bavím o klasickém řazení.

PS: Je možné provést citaci z telefonu? Označí text, ale tlačítko Citovat nefunguje. Manuálně se na to můžu vykašlat.
Radek9
Profil
Prochy:
Tvoje řešení se tady aplikovat určitě nedá, jelikož když bude mít uživatel více typů karet např. CP, CD, tak by mu to uprednostnilo CP1000 před CD800, pokud se bavím o klasickém řazení.
Jasně. To řazení podle délky je vhodné jen na vybírání posledního prvku. Pro tyhle účely určitě ne. Tam už to budeš muset nějak rozseknout na textovou a numerickou část.

PS: Je možné provést citaci z telefonu? Označí text, ale tlačítko Citovat nefunguje.
V Chromu na Androidu mi to normálně funguje.
Prochy
Profil
Radek9:
Jasně. To řazení podle délky je vhodné jen na vybírání posledního prvku.
Jasný, já jsem právě jen uváděl, kde vidím snad jediný další problém kvůli špatnému návrhu, což je akorát špatné řazení v přehledu, doufám.

V Chromu na Androidu mi to normálně funguje.
Já používal doteď nativní prohlížeč Androidu(Xiaomi) a tam mi to nefunguje, zkusil jsem Chrome a tam ano.

Ještě jednou díky. :)

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: