Just SQL Report - JSR
Egyszerű és hatékony SQL alapú riportkészítés
Ebben a példában egy gyors és hatékony SQL alapú riportkészítési megoldást mutatok be. A riportok HTML, PDF és Excel formátumban is megtekinthetők.
Bár ez az eszköz nem alkalmas minden típusú riport előállítására, éppen ez adja az előnyét: könnyen használható és nagyon gyors, ami a legtöbb gyakorlati esetben teljes mértékben elegendő.
A legtöbb riport master-detail (mester-részlet) típusú, vagyis az adatok jellemzően két szinten jelennek meg. A JSR nevű riportgenerátor azonban akár 5 szintű adathierarchiát is támogat, vagyis a következőt:
master → detail → detail → detail → detail
A módszer lényege, hogy mindössze egyetlen SQL SELECT lekérdezést kell készítenünk, amely tartalmazza a master,s detail, subdetail stb. mezőket. A JSR automatikusan felismeri a különböző adatszintek közötti kapcsolatot, a riport struktúrája alapján.
A működés logikája
A riport egyes részei panelokra (band-ekre) vannak felosztva.
A JSR belső működése azon az elven alapul, hogy két egymást követő, azonos szinten lévő panel nem tartalmazhat teljesen megegyező adatokat.
Ez az elv lehetővé teszi, hogy a JSR hatékonyan meghatározza, melyik adat melyik panelban jelenjen meg – anélkül, hogy külön adatcsoportosításokat vagy extra logikát kellene hozzáadnunk.
Lássunk erre egy egyszerű példát.
Users tábla adatai:
ID | FirstName | LastName | Born |
---|---|---|---|
1 | Johan | Wagner | 1980-06-02 |
2 | Paul | Noringed | 1970-01-02 |
3 | Johan | Wagner | 2001-10-05 |
Projects tábla adatai azt mutatja, hogy egy user milyen projekkel rendelkezik:
ID | ProjName | UserID | Badzet |
---|---|---|---|
1 | Slovak Telekom | 1 | 10000,50 |
2 | France Telekom | 2 | 25689,50 |
3 | Deutche Telekom | 3 | 31200,90 |
4 | Pierte Hungary | 1 | 1500,00 |
5 | Cargo Slovakia | 2 | 58000,00 |
6 | Penta Slovakia | 1 | 1567,70 |
SELECT FirstName, LastName, ProjName, Badzet
FROM Users
LEFT JOIN Projects ON UserID = Users.ID
ORDER BY FirstName, LastName, ProjName
UID | FirstName | LastName | ProjName |
---|---|---|---|
3 | Johan | Wagner | Deutche Telekom |
1 | Johan | Wagner | Penta Slovakia |
1 | Johan | Wagner | Pierte Hungary |
1 | Johan | Wagner | Slovak Telekom |
2 | Paul | Noringed | Cargo Slovakia |
2 | Paul | Noringed | France Telekom |
Készítsunk egy egyszerű riportot:
[REPORT]
report="Report Title"
comment="my comment1"
comment="my comment2"
comment="generted: %date %time"
[band=1] top="20px"
<fld=FirstName> width="130" style="font-weight:bold; border: 2px solid gray; height:25px;text-align:center;"
<fld=LastName> width="130" style="font-weight:bold; border: 2px solid gray; height:25px;text-align:center;"
[summary=1] top="20px"
<fld=COUNT(FirstName)> prefix="Users: " width="195" style="border: 2px solid gray; text-align:center;" <column=Summary> style="font-weight:bordel;height:25px;"
[SQL]
SELECT FirstName, LastName
FROM Users
ORDER BY FirstName, LastName
Ebben a riportban érdemes észrevenni, hogy két azonos nevű felhasználó van, ami két különböző embert jelöl, más születési dátummal, de a születési dátumot, nem akarjuk megjeleníteni, mert bizalmas információ.
Itt ez még nem jelent gondot, mivel ennek a panelnak (band=1) nincs kapcsolata más alárendelt panellal, ezért a riport nem ellenőrzi azt, hogy ugyanazok az adatok jelennek meg azonos panelban.
A következő, lenti példában viszont már más lesz a helyzet.
Egy master-detail riport a userek projektjeivel:
[REPORT]
report="Report Title"
comment="my comment1"
comment="my comment2"
comment="generted: %date %time"
[band=1] top="20px"
<fld=@UID>
<fld=SERIAL()> width="30" style="font-weight:bold; border: 2px solid gray; height:25px;text-align:center;"
<fld=FirstName> width="130" style="font-weight:bold; border: 2px solid gray; height:25px;text-align:center;"
<fld=LastName> width="130" style="font-weight:bold; border: 2px solid gray; height:25px;text-align:center;"
[band=2] top="-1px" left="10px"
<fld=SERIAL()> width="30" <column=N.> style="font-weight:normal;"
<fld=ProjName> width="150" style="text-align:center; color:navy;" <column=Project> style="font-weight:normal;"
<fld=ROUND2(Bt)> width="150" sufix=" €" <column=Badzet> style="font-weight:normal;"
[summary=2] top="10px" left="10px"
<fld="..."> width="30" style="border: 2px solid silver";
<fld=COUNT(ProjName)> prefix="Projects: " width="148" style="border: 2px solid silver; text-align:center;";
<fld=ROUND0(SUM(Bt))> prefix="Badzet ∑: " width="149" style="border: 2px solid silver"; sufix=" €"
[summary=1] top="20px" left="0px"
<fld=COUNT(UID)> prefix="Users: " width="95" style="border: 2px solid gray; text-align:center;" <column=Summary> style="font-weight:bordel;height:25px;" colspan="3";
<fld=COUNT(ProjName)> prefix="Projects: " width="95" style="border: 2px solid gray; text-align:center;"
<fld=ROUND0(SUM(Bt))> prefix="Badzet ∑: " width="150" style="border: 2px solid gray;" sufix=" €"
[SQL]
SELECT Users.ID as UID, FirstName, LastName, Badzet as Bt
FROM Users
LEFT JOIN Projects ON UserID = Users.ID
ORDER BY FirstName, LastName, ProjName
Ebben a reportban 2 panelban (band=1, band=2) jelennek meg az adatok. Mindkét panelnak van egy összegző panelja is (summary=2, summary=1).
A adatok megjelenitetésének dizajnját a stílus adja meg, ami azonos a jól ismert a HTML stílussal.
Ebben a példában minden mezőnek megvan adva a stílusa, amit természetesen egyszerűsíteni lehet class hivatkozással, a gyakran használt stílusok számára.
Egyetlen fontos dolog, amit észre kell venni a <fld=@UID>, ami egy olyan mezőre hivatkozik, amit nem akaruk megjeleníteni (not visible: @FieldName),
de mégis fontos, mert ennek alapján a riport megtudja különböztetni a két azonos nevű felhasználót, hogy két különböző személyről van szó.
Ha ezt sort <fld=@UID> kihagynánk, akkor a riport nem tudná megkülönböztetnia két azonos nevű felhasználót és az alábbi módon jelennénk meg ez az adatok:
Itt fontos észrevenni, hogy a riport nem az SQL adataira támaszkodik, hanem azokra az adatokra, amikre hivatkozást adunk a riportnak fld mezőben.
Csak ezeket az adatokat figyeli és csak ezeken az adatokon lehet megszámlálást COUNT(...) és összegzést SUM(...) végrehajtani az összegző panelban. Tehát a summarizációs panelban csak olyan mezők szerepelhetnek, melyek szerepeltek
az adott panelban is, melyeket átadtunk a riportnak.
Szintén nagyon fontos az adatok sorbarendezése. Ha az datok nincsenek megfelelően sorbarendezve (order by), akkor a riport nem tudja helyesen felismerni, hogy az adatok hová tartoznak, melyik panelba kell tenni őket.
A JSR program értékelése
A JSR program használata egyszerű, futása gyors és a riportnak csak egy kis része foglalja a memóriát, mivel folyamatosan fájba töténik a riport kimentése.
Ezért alkalmas nagy terjedelmű riportok generálására, HTML, PDF, EXCEL formátumban és lehetőséget nyújt a vonalkód megjelenitésre is.
Hátránya, hogy logikájából következően nem általános és bizonyos adatelőkészítést vagy operációkat az adatbazis szintjén (vagy a SQL lekérdezés szintjén) kell elvégezni.
Természetesen ha a JSR egy programozási nyelvbe van ágyazva (pl. Go, Delphi, Python, Java), mint komponens, akkor a számítási lehetőségek nagyban kibővülnek és composite report készítésre is alkalmas lehet.