2009. január 21., szerda

Tekerés SQL-ben - PIVOT nélkül

Egy érdekes problémába ütköztem ma. Adott egy adatbázis, elég speciális szerkezettel: nem egy-egy entitás-típushoz tartozik egy-egy tábla, hanem a tulajdonság-típusokhoz: egy tábla a hosszú szövegeknek, egy a binárisoknak... Ilyet akkor szokás csinálni, ha a séma gyakran változik (pl. azért, mert a felhasználó kezébe adjuk a séma módosításának lehetőségét).
A probléma (némileg leegyszerüsítve) ott kezdődött, hogy volt egy "FlatProperties" tábla, amiben a rövid, nvarchar(kevés) típusú tulajdonságok voltak tárolva. Ezekből sok volt egy sorban, Nvarchar1, Nvarchar2... és így tovább. Végtelen sok persze nem lehet, ez a limitáció úgy lett feloldva, hogy minden sor kapott még egy Page mezőt is, ezzel kvázi tényleg a végtelenbe tolva ki a lehetőségek számát.
Jó lett volna viszont, ha egy SQL-lel az egy adott entitáshoz tartozó, éppen minket érdeklő adatokat össze lehet gereblyézni egy sorba.

Futottam pár kört a PIVOT-tal, de úgy tűnt, nem ő lesz az én barátom.
Egy igazi svájcibicskára volt szükségem: a CASE-re. Ezzel meg lehet oldani, hogy az eredményhalmazban az aktuális Page indextől függő oszlopokat generáljunk.
Volt még egy kis bibi: egy entitáshoz továbbra is több sor tartozott, azaz a Page-ek megmaradtak külön soron. Nosza, még egy GROUP BY, méghozzá GROUP BY VersionId: az egyes csoportok máris az egyes adott enitiáshoz (jelen esetben verzióhoz) tartoznak. Végül valami ilyesmi lett:

SELECT
    VersionId,
    MAX (CASE WHEN Page = 0 THEN Nvarchar1 END) AS Nvarchar1_Page0,
    MAX (CASE WHEN Page = 0 THEN Nvarchar2 END) AS Nvarchar2_Page0,
    MAX (CASE WHEN Page = 1 THEN Nvarchar1 END) AS Nvarchar1_Page1,
    MAX (CASE WHEN Page = 1 THEN Nvarchar2 END) AS Nvarchar2_Page1,    
    MAX (CASE WHEN Page = 2 THEN Nvarchar1 END) AS Nvarchar1_Page2,
    MAX (CASE WHEN Page = 2 THEN Nvarchar2 END) AS Nvarchar2_Page2
FROM
    FlatProperties
GROUP BY
    VersionID

0 megjegyzés:

Megjegyzés küldése