A q-sql a hagyományos adatbázis-kezelő rendszerek SQL-jéhez hasonló lekérdezőnyelv. Teljesen integrálva van a q-val, így a kifejezések tartalmazhatnak q függvényeket, egy q függvény visszaadhatja egy lekérdezés eredményét stb.
Az SQL-hez hasonlóan a q-sql-ben is az alapvető művelet a select. Egy select kifejezés az alábbi részekből épülhet fel:
select [distinct] mezők [by mezők] from tábla [where megszorítások]
A legegyszerűbb formában minden opcionális elemet elhagyunk:
A select kulcsszó után felsorolhatjuk azokat a mezőket, amelyeket meg akarunk kapni. Vigyázzunk, mert ekkor a kulcsmezők már nem lesznek kulcsok:
Az SQL-hez hasonlóan használhatjuk a distinct kulcsszót a duplikátumok kiszűrésére. Ez egyébként a q-ban listafüggvényként is megtalálható, viszont speciális jelentése van, ha közvetlenül a select után írjuk, és nem zárójelezzük egybe a mezőnevekkel.
A where kulcsszóval szűrőfeltételeket adhatunk meg. Több feltételt vesszővel választhatunk el, ezért ha a konkatenáció operátort is szeretnénk használni, be kell zárójeleznünk a kifejezést.
Lekérdezések során a tábla kiegészül egy rejtett i nevű mezővel, amely a sorszámokat tartalmazza. Ezt is belevehetjük az eredménybe, és akár kifejezésekben is felhasználhatjuk.
A where kifejezésben az oszlopnevek az egész oszlopra mint listára vonatkoznak, nem az egyes elemekre, mint az SQL-ben. Azonban a q atomi műveleteinek köszönhetően a legtöbb feltétel leírható az SQL-ben megszokott módon. Pl. a "status<=20" kifejezésben a "=<" operátor egy listát és egy atomot kap paraméterül, ezért a lista minden egyes elemére végrehajtódik. Az eredmény egy boolean lista, ahol pontosan azok az elemek lesznek 1b (true) értékek, ahol a status oszlopban 20-nál nagyobb vagy egyenlő érték található. A where feltétel ez alapján szűri a sorokat. Célszerű azokat a feltételeket rakni elsőnek, amelyek a legtöbb sort fogják kidobni az eredményből.
A mezőlistában megadhatunk számított mezőket is. Ezekben a kifejezésekben a mezőnevek szintén az egész oszlopot jelölik. A "többi mező" jelölésére szolgáló csillag azonban nem szerepel a q-ban. Ha csak bővíteni szeretnénk a táblát, használjuk az update műveletet.
A by kulcsszó után megadhatunk mezőket, amelyek alapján a sorokat csoportosítani akarjuk. A csoportosító mezők az eredményben kulcsok lesznek.
SQL-ben van egy olyan korlátozás, hogy a GROUP BY-ban nem előforduló mezők nem szerepelhetnek az eredményben, kivéve ha valamilyen aggregáló függvényt alkalmazunk rájuk. Ez a korlátozás a q-ban nincs benne, és érdekes anomáliákat tapasztalhatunk, ha kihasználjuk ezt a hiányt. Ha nem sorolunk fel a select után mezőket, akkor az egyes csoportokból csak az utolsó sor marad meg, ha viszont felsoroljuk a mezőket, akkor egy csoporthoz csak egy sor fog tartozni, ahol a nem csoportosító mezőkből lista keletkezik. A helyes eredményt az "ungroup" függvény alkalmazásával kapjuk meg, de természetesen az SQL-hez hasonlóan az egyes mezőket is aggregálhatjuk az arra szolgáló függvényekkel (pl. first, last, min, max, avg, sum).
Az exec utasítás szintaxisa és szemantikája szinte teljesen megegyezik a select-ével, a különbség az eredmény típusában van. A select mindig táblát ad vissza. Az exec egy listát ad vissza, ha az eredmény egy oszlop, és egy listákból álló szótárat, ha az eredmény több oszlop.
Az update utasítás hasonlít a select-hez, a különbség az, hogy kiválasztások helyett módosításokat kell felsorolni. A művelet érintetlenül hagyja a nem módosított oszlopokat, és azokat a sorokat, amelyekre a where feltétel (ha van) hamis értéket ad vissza.
Az SQL-lel ellentétben a q delete utasítása oszlopot is tud törölni a táblából. Sorokat is törölhetünk, ha where feltétellel megadjuk a törlendő sorok tulajdonságait. Viszont a kettő egyszerre nem működik.
Az update és delete műveletek nem módosítják a táblát, csak visszaadnak egy új táblát, amelyben már benne van a módosítás eredménye. Lehetőség van a helyben módosításra is, ha a tábla nevét szimbólumként adjuk át.
Az SQL-hez hasonlóan a q is lehetőséget ad táblák összekapcsolására.
Egy mezőt úgy tehetünk idegen kulccsá, hogy típusként megadjuk neki a hivatkozott tábla nevét. Ekkor a mező értékei csak a hivatkozott tábla kulcsának értékeit vehetik fel.
Az idegen kulcsok megjelennek a tábla metaadatai között is.
SQL-ben az összekapcsoláshoz általában explicit ki kell írnunk a feltételeket. q-ban az idegen kulcsos összekapcsolás automatikus. Ha a select kifejezésben a tábla idegen kulcsot tartalmaz, a kapcsolt tábla mezői elérhetőek, ha az idegenkulcs-mező nevével prefixáljuk őket.
Az idősoros adatok kezelése a kdb+ egyik legnagyobb erőssége. Például egy táblában tárolhatjuk néhány részvény árát bizonyos időpontokban. Azt feltételezzük, hogy a részvény ára konstans, ha nem érkezik rá új ár:
Például a fenti adatok alapján az `AAPL részvény értéke 2012. januárban végig 100, február 1-től pedig 200. Az idősoros összekapcsolás (asof join) pontosan ezt fejezi ki. Az első paraméter egy tábla, amelynek van egy dátum/idő oszlopa. A második paraméter lehet egy szótár vagy egy tábla, amely hivatkozik a tábla egy oszlopára és az időre. Az eredmény megadja, milyen érték tartozik a megadott elemhez az adott időpontban.
A tábla lemezen való tárolása fontos feladat, mivel az adatbázis-kezelő processz összeomlása után is szeretnénk megtartani az adatainkat.
Nagyobb tábláknál hasznos az a módszer, hogy minden oszlopot külön fájlban tárolunk. Ezt a műveletet a q nyelv natívan támogatja. Használatához egyszerűen egy könyvtárnevet kell megadnunk a végén / jellel (szemben a szokásos mentéssel, amikor ez a jel hiányzik).
Sajnos csak kulcs nélküli és nem enumerálható szimbólumot nem tartalmazó táblát lehet ilyen módon kimenteni. A szimbólumokra vonatkozó megszorítás elég kemény. A legkönnyebb megoldás, ha a .Q.en függvénnyel enumeráljuk a szimbólumokat, ezáltal létrejön egy "sym" nevű fájl, amely tartalmazza az összes szimbólumot.