Schamann.net

…děláme vJeci jinak…

You are currently browsing the SQL category.

MySQL – tisk adresních štítků

Narazil jsem na zajímavý problém s tiskem adresních štítků z naší databáze. Potřeboval jsem odesílat více balíků z jedné zakázky na stejnou adresu. Normálně jsme tiskli jeden štítek několikrát. Ale stalo se, ze kurýr u zákazníka nevěděl kolik balíků má ve skutečnosti předat. Takže jsem chtěl udělat číslování balíků v rámci zakázky ve formátu 1z5, 2z5, atd. Řešení je tak překvapivě jednoduché, že jsem se o něj chtěl podělit.

Jasné, řešení existuje spousta a každý programátor i začátečník by si s tím nějak poradil po svém. Ale protože v našem .NET používáme pro tisky CrystalReport bylo by elegantní řešení nechat to přímo na databázi a výsledek podstrčit rovnou z MySQL. To znamená ve výsledném SELECTU chci úmyslně tolik duplicitních řádků adres, kolik mám balíků a zároveň doplnit číslování těch duplicit, aby mi vznikla kompletní sada adresních štítků.

I tady existuje několik možností přes dočasné tabulky nebo nějaké funkce, všechno mi přišlo zbytečně složité. Ale pojďme postupně.

Pokud JOINuju dvě tabulky, které mají různý počet řádků, buď mi vzniknou duplicity nebo bude něco chybět. Pojďme tedy využít těch duplicit a jen je očíslovat.

Jak na to? Důležité je vyrobit si očíslovaný seznam v jiné tabulce, která bude sloužit pro získání pořadí. Buď se dá založit nějaká dočasná tabulka, která bude seznam obsahovat, například:

CREATE TABLE max_baliku (PORADI INT(11) PRIMARY KEY)
INSERT INTO max_baliku VALUES(1),(2),(3),(4),(5)

Musí se ovšem, předem zjistit maximální počet balíků ve všech adresách (pokud tisknete štítky, tak jako my, v dávkách) které chci tisknout, a po tisku po sobě zase uklidit. To znamená čas a kódování navíc. Protože je tohle u nás celkem pravidelná věc, tak jsem jednoduše založil tabulku ciselnik_max_baliku s jediným sloupcem PORADI, který obsahuje číselník s dostatečnou rezervou (100) řádků.

Pro ucelený příklad mějme ještě tabulky adresy a baliky:

  • adresy.CISLO_ZASILKY, adresy,ADRESA
  • baliky.CISLO_ZASILKY , baliky.POCET_BALIKU

JOINovat umíme všichni a spojení 3 tabulek dáme do kupy velice rychle:

SELECT a.ADRESA, c.PORADI, b.POCET_KUSU 
FROM adresy AS a
LEFT JOIN baliky AS b ON b.CISLO_ZASILKY = a.CISLO_ZASILKY
LEFT JOIN ciselnik_max_baliku AS c ON c.PORADI = b.POCET_KUSU  

A je čas na kouzlo. Celý fígl je v tom že v klauzuli ON se nemusí používat pouze „=“ jak jsem všichni notoricky zvyklí, ale můžeme použít libovolný operátor. A pokud použiju v našem případě „<=“ vznikne přesně to co potřebuju: Očíslovaný seznam adresních štítků. Ono „<“ totiž pak bude vyhovovat všem řádkům z tabulky ciselnik_max_baliku az do hodnoty baliky.POCET_KUSU a tyto řádky do výsledku přidá a protože k nim v tabulce adres nejsou protihodnoty musí je zduplikovat. Nakonec ještě nějaký ORDER, aby se vytiskly ve správném pořadí a je hotovo.

SELECT a.ADRESA, c.PORADI, b.POCET_KUSU 
FROM adresy AS a
LEFT JOIN baliky AS b ON b.CISLO_ZASILKY = a.CISLO_ZASILKY
LEFT JOIN ciselnik_max_baliku AS c ON c.PORADI <= b.POCET_KUSU
ORDER BY a.CISLO_ZASILKY, c.POCET
Jak jsem řekl, překvapivě jednoduché a elegantní řešení, bez jakýchkoliv
dalších cyklů, selektů, funkcí a zbytečného kódování...


  • 🙂

Posted 2 months ago at 00:51.

Add a comment

MySQL Error 1030 – Got error 134

MySQL Error

1030 – Got error 134 from storage engine

Chyba se objeví při čtení z poškozené tabulky. Nemusí být nutně poškozená, stačí špatné indexy, nebo něco není úplně správně (například čtení už vymazaného řádku a pod.).  Nepátral jsem v tom hluboce, stačilo opravit tabulku.

REPAIR TABLE nazev_tabulky

Posted 8 years, 2 months ago at 01:09.

Add a comment

Data truncated for column

Chyba

Data truncated for column ‚x‘ at row 1

znamená, že se do databáze snažíte vložit číslo ve formátu, který není shodný s formátem slopce do kterého hodnotu vlkádáte.

Tabulka má sloupec definovaný jako INT(99)

a snažím se vkládat hodnotu Single: 188,53

Řešení – upravit výstupní hodnotu na formát jaký podporuzje databáze, napr.:

Round(188,53 , 0)

Posted 9 years ago at 00:07.

Add a comment

Předposlední záznam

Pro výběr předposledního záznamu v tabulce se da jednoduše použít tato konstrukce:

SELECT * FROM (

SELECT * FROM `vvv_00773400466_code_apl`
ORDER BY `vvv_00773400466_code_apl`.`ID` DESC LIMIT 2

) AS tmp ORDER BY tmp.ID ASC LIMIT 1

Jednoduché a elegantní…

Posted 9 years ago at 13:10.

Add a comment

DELETE

Smazat řádky od Cislo_Radku (včetně) z tabulky Nejaka_Tabulka.
DELETE FROM Nejaka_Tabulka WHERE ID >= ‚Cislo_Radku‘

Posted 9 years, 8 months ago at 20:17.

Add a comment