Adatbázisok

Alap SQL

Az SQL a Structured Query Language (strukturált lekérdezőnyelv) rövidítése, amelyet a relációs adatbáziskezelők lekérdezésére (és módosítására) használnak. Kiejtése magyarul es-kú-el, angolul esz-kjú-el, de gyakran előfordul a szíkvel is.

Adatbázis szintű SQL parancsok

Adatbázis létrehozása és törlése

CREATE DATABASE testDB;
DROP DATABASE testDB;

Tábla létrehozása, módosítása, törlése

CREATE TABLE Persons (
    PersonID int,
    LastName varchar(255),
    FirstName varchar(255),
    Address varchar(255),
    City varchar(255) 
);
DROP TABLE Shippers;
TRUNCATE TABLE Shippers;
ALTER TABLE table_name ADD COLUMN column_name datatype;
ALTER TABLE table_name MODIFY COLUMN column_name datatype;
ALTER TABLE table_name DROP COLUMN column_name;

Lekérdező SQL parancsok

SELECT

SELECT * FROM Customers;
SELECT CustomerName, City FROM Customers;
SELECT DISTINCT Country FROM Customers;
SELECT CustomerID as ID, CustomerName AS Customer FROM Customers;
SELECT CustomerName, Address + ', ' + PostalCode + ' ' + City + ', ' + Country AS Address FROM Customers;

WHERE

SELECT * FROM Customers WHERE Country='Mexico';

WHERE feltétel példák:

- columnName = value
- columnName LIKE 'pattern%'
- columnName IS NULL
- columnName IN ('listElement1', 'listElement2')
- columnName1 IN (SELECT columnName2 FROM table2)
- columnName BETWEEN x AND y
- EXISTS (SELECT columnName FROM table WHERE condition)
- columnName1 = ANY (SELECT columnName2 FROM table2 WHERE condition2)
- columnName1 = ALL (SELECT columnName2 FROM table2 WHERE condition2)
- condition1 AND condition2
- condition1 OR condition2
- NOT condition

TOP

SELECT TOP 3 * FROM Customers;
SELECT * FROM Customers LIMIT 3;
SELECT TOP 50 PERCENT * FROM Customers;

UNION

SELECT City FROM Customers UNION SELECT City FROM Suppliers;
SELECT City FROM Customers UNION ALL SELECT City FROM Suppliers;

Matematikai függvények

SELECT MIN(Price) AS SmallestPrice FROM Products;
SELECT MAX(Price) AS LargestPrice FROM Products;
SELECT COUNT(ProductID) FROM Products;
SELECT AVG(Price) FROM Products;
SELECT SUM(Quantity) FROM OrderDetails;

ORDER BY

SELECT * FROM Customers ORDER BY Country;
SELECT * FROM Customers ORDER BY Country ASC, CustomerName DESC;

GROUP BY, HAVING

SELECT COUNT(CustomerID), Country FROM Customers GROUP BY Country;
SELECT COUNT(CustomerID), Country FROM Customers GROUP BY Country HAVING COUNT(CustomerID) > 5;

Illesztés (join)

Az illesztéssel két adattáblából új, virtuális adattáblát tudunk létrehozni. Példaként vegyünk egy általános esetet: vannak vásárlók, áruk és vásárlások. Egy várásló tetszőleges számú árufajtát vásárolhat, és egy árufajtából tetszőleges számú vásárló vásárolhat. A példában legyen három vásárló: Sanyi, Juli és Peti, valamint három áru: alma, banán és csoki. Sanyi almát és csokit vesz, Juli csak csokit, Peti semmit. A következő módon lehet adattáblákat illeszteni:

  • JOIN, INNER JOIN: csak azokat az elemeket adja vissza, amelyek minkét táblában benne vannak A példában: Sanyi - alma, Sanyi - csoki, Juli - csoki.
  • LEFT JOIN, LEFT OUTER JOIN: a bal táblában levő összes elemet visszaadja, valamint a kapcsolódó elemeket a jobb táblából. A példában: a fenti három, valamint Peti - [üres].
  • RIGHT JOIN, RIGHT OUTER JOIN: a jobb táblában levő minden elemet visszaadja, valamint a kapcsolódó elemeket a bal táblából. A példában: az első három, valamint [üres] - banán.
  • FULL JOIN, FULL OUTER JOIN: azokat az elemeket adja vissza, amelyek legalább az egyikben szerepelnek. A példában: a fenti öt.
SELECT Orders.OrderID, Customers.CustomerName, Orders.OrderDate FROM Orders JOIN Customers ON Orders.CustomerID=Customers.CustomerID;

Módosító SQL parancsok

UPDATE

UPDATE Customers SET ContactName = 'Alfred Schmidt', City= 'Frankfurt' WHERE CustomerID = 1;

INSERT/SELECT INTO

INSERT INTO Customers (CustomerName, City, Country) VALUES ('Bob', 'New York', 'USA');
INSERT INTO Customers (CustomerName, City, Country) SELECT SupplierName, City, Country FROM Suppliers;
SELECT * INTO CustomersGermany FROM Customers WHERE Country = 'Germany';

DELETE

DELETE FROM Customers WHERE CustomerName='Bob';

Haladó SQL fogalmak

Nézet (view)

A nézet (view) egy virtuális tábla, ami egy SQL lekérdezés eredménye.

CREATE VIEW ViewName AS SELECT Column1, Column2 FROM TableName WHERE SomeColumn = SomeValue;
SELECT * FROM ViewName;
DROP VIEW ViewName;

Megszorítás (constraint)

CREATE TABLE table_name (
    column1 datatype constraint,
    column2 datatype constraint,
    column3 datatype constraint,
    ....
);

Az alábbi megszorítások a legelterjedtebben az SQL-ben:

  • NOT NULL - az adott oszlop nem tartalmazhat NULL értéket (pl. egy vásárlásnál nem hiányozhat a vásárlás összege)
  • UNIQUE - egy oszlop összes eleme különböző (pl. egy telefonszám táblában ne lehessen két egyforma telefonszám)
  • PRIMARY KEY - egyértelműen azonosítja a tábla sorait (a NOT NULL és UNIQUE egyszerre)
  • FOREIGN KEY - egyértelműen azonosítja egy másik tábla során
  • CHECK - biztosítja, hogy egy oszlop összes eleme adott feltételnek felel meg (pl. az e-mail cím tartalmazza a @ karaktert)
  • DEFAULT - alapértelmezett értéket ad azoknak az oszlopoknak, ahol nincs megadva érték (pl. ha a távolság mértékegységét kell megadni, akkor az alapértelmezett lehet méter)
CREATE TABLE Persons (
    ID int NOT NULL PRIMARY KEY,
    LastName varchar(255) NOT NULL,
    FirstName varchar(255),
    Age int CHECK (Age>=18)
    City varchar(255) DEFAULT 'Sandnes'
    CONSTRAINT UC_Person UNIQUE (ID,LastName)
);

CREATE TABLE Orders (
    OrderID int NOT NULL,
    OrderNumber int NOT NULL,
    OrderDate date DEFAULT GETDATE()
    PersonID int,
    PRIMARY KEY (OrderID),
    CONSTRAINT FK_PersonOrder FOREIGN KEY (PersonID)
    REFERENCES Persons(PersonID)
);

ALTER TABLE Orders ADD CONSTRAINT FK_PersonOrder FOREIGN KEY (PersonID) REFERENCES Persons(PersonID);

Index

Az index olyan keresési tábla, melynek segítségével a kereső fel tudja gyorsítani az adatletöltést.

CREATE [UNIQUE] INDEX index_name ON table_name (column1, column2, ...);
DROP INDEX index_name;

A UNIQUE oszlopokra (gy az elsődleges kulcsokra is) automatikusan készül index. A tárolási mód platformfüggő, pl. az Oracle adatbázisban ALL_INDEXES, USER_IND_COLUMNS.

SQL kiegészítések

Az alap SQL szabványos, és többé-kevésbé ugyanúgy működik mindegyik rendszeren. Ez viszont nem alkalmas minden cél megvalósítására, pl. bonyolultabb logika megfogalmazására. Így minden gyártó arra kényszerül, hogy saját, tehát platformfüggő kiegészítést hozzon létre. Ebben a részben ezt nézzük meg.

PL/SQL

Ez az Oracle procedurális SQL kiegészítője.

Alap szintaxis

-- comment
DECLARE 
   declarations;
BEGIN 
   statements;
END;
/

Kiírás

dbms_output.enable
dbms_output.put_line('String: ' || value);

Változók

variable_name [CONSTANT] datatype [NOT NULL] [:= | DEFAULT initial_value]

A leggyakoribb adattípusok:

INTEGER, REAL, VARCHAR2(length), BOOLEAN, DATE, TIMESTAMP

A felhasználó is definiálhat típust:

SUBTYPE newType IS type;

A változók hatóköre

DECLARE 
    -- Global variables  
    declarations;
BEGIN
    statements;
    DECLARE
        -- Local variables 
        declarations;
    BEGIN 
        statements;
    END;  
END;

Oszlop típus használata

DECLARE 
    variable table.column%type;
BEGIN 
    SELECT column INTO variable FROM table where id=15;
    ...
END;

A leggyakoribb string műveletek:

CONCAT(x, y), LENGTH(x), LOWER(x), TRIM(x), UPPER(x)

Adatszerkezetek (collections)

Asszociatív tömb: kulcs-érték párok

TYPE typeName IS TABLE OF elementType INDEX BY subscriptType; 
myAssicateiveArray(mySubscript):= myElement;

Beágyzott távlázat: dinamikus növekedés, lehet ritka.

TYPE typeName IS TABLE OF elementType;

Változó méretű tömb:

TYPE typeName IS VARRAY(n) of elementType;

Eljárások:

EXISTS(n), COUNT, LIMIT, FIRST, LAST, NEXT(n), DELETE, ...

Feltételkezelés

IF condition1 THEN  
    statements; 
ELSIF condition2 THEN 
    statements; 
ELSE  
    statements; 
END IF; 

CASE selector 
    WHEN 'value1' THEN statements1; 
    WHEN 'value2' THEN statements2; 
    ... 
    ELSE statementsN;  -- default case 
END CASE;

CASE 
    WHEN selector = 'value1' THEN statements1; 
    WHEN selector = 'value2' THEN statements2; 
    ...
    ELSE statementsN;  -- default case 
END CASE;

Ciklus

LOOP
    ...
        EXIT;
    ...
        CONTINUE;
    ...
END LOOP; 

WHILE condition LOOP 
    statements; 
END LOOP; 

FOR counter IN initial_value .. final_value LOOP 
    statements; 
END LOOP;

<< label >>
statements;
...
GOTO label;

Eljárások, függvények

CREATE [OR REPLACE] PROCEDURE procedureName(parameters) {IS | AS} 
BEGIN
    statements;
END procedureName;

DROP PROCEDURE procedureName; 

CREATE [OR REPLACE] FUNCTION functionName(parameters) RETURN return_datatype {IS | AS} 
BEGIN 
    statements;
END functionName;

Paraméterek:

parameterName [IN | OUT | IN OUT] type [, ...]

Végrehajtás:

EXECUTE procedure_name;
EXECUTE function_name(parameters);
BEGIN
     ...
     procedure_name;
     result := function_name(parameters);
     ...
END;

Kurzorok

Implicit kurzor:

SQL%FOUND, SQL%NOTFOUND, SQL%ISOPEN, SQL%ROWCOUNT

Explicit kurzor:

DECLARE 
    var1 table.column1%type; 
    var2 table.column2%type; 
    CURSOR cursor_name IS SELECT column1, column2 FROM table; 
BEGIN 
    OPEN cursor_name;
    LOOP
        FETCH cursor_name INTO var1, var2; 
        EXIT WHEN cursor_name%notfound; 
        dbms_output.put_line(var1 || ' ' || var2); 
    END LOOP; 
    CLOSE cursor_name;
END;

Rekordok

DECLARE 
    myRecord table%rowtype; 
BEGIN 
    SELECT * into myRecord FROM table WHERE ...;  
    dbms_output.put_line(myRecord.column1 || ' ' || myRecord.column1); 
END;

Kurzort is használhatunk. Felhasználó által definiált rekord:

TYPE typeName IS RECORD (
    fieldName1 datatype1,
    fieldName2 datatype2,
    ...
    fieldNameN datatypeN
);
recordName typeName;

Kivételkezelés

DECLARE
    declarations;
    myException EXCEPTION; 
BEGIN 
    statements;
    IF condition THEN 
        RAISE myException; 
    END IF; 
EXCEPTION 
    WHEN exception1 THEN  
        statements1;
    ...
    WHEN exceptionN THEN 
        statementsN;
    WHEN myException THEN 
        statementsMy;
END;

Rendszer kivételek:

CASE_NOT_FOUND, COLLECTION_IS_NULL, INVALID_CURSOR, INVALID_NUMBER, LOGIN_DENIED, NO_DATA_FOUND, PROGRAM_ERROR, ZERO_DIVIDE, ...

Kiváltó utasítások (trigger)

CREATE [OR REPLACE ] TRIGGER trigger_name {BEFORE | AFTER | INSTEAD OF} 
{INSERT [OR] | UPDATE [OR] | DELETE} [OF col_name] ON table_name  
[REFERENCING OLD AS o NEW AS n] [FOR EACH ROW]  
WHEN (condition)   
DECLARE 
    declarations; 
BEGIN  
    statements 
EXCEPTION
    exceptionHandlingStatements 
END;

Tranzakciók

COMMIT;
ROLLBACK;
SAVEPOINT < savepoint_name >;
...
ROLLBACK [TO SAVEPOINT < savepoint_name>];

Csomagok

CREATE PACKAGE myPackage AS
    PROCEDURE myProcedure(parameters);
    PROCEDURE ...;
END myPackage;

CREATE OR REPLACE PACKAGE BODY myPackage AS  
    PROCEDURE myProcedure(parameters) IS 
        declarations;
    BEGIN
        ...
    END myProcedure;
    ...
END myPackage;

Objektumorientáltság

CREATE OR REPLACE TYPE MyClass AS OBJECT (
    myAttribute1 type1;
    myAttribute2 type2;    
    MEMBER FUNCTION myFunction(parameters) RETURN type;
    MEMBER PROCEDURE myProcedure;
); 

CREATE OR REPLACE TYPE BODY MyClass AS 
    MEMBER FUNCTION myFunction(parameters) RETURN type IS 
    BEGIN 
        statements;
        RETURN result;
    END myFunction;

    MEMBER PROCEDURE myProcedure IS
    BEGIN 
        statements;
    END myProcedure;
END;

DECLARE
    myInstance MyClass;
BEGIN 
    myInstance1 := myClass(param1, param2); 
    ...
END;

Összehasonlítás

MAP MEMBER FUNCTION measure RETURN NUMBER; -- absolute value
ORDER MEMBER FUNCTION measure(other MyClass) RETURN NUMBER; -- -1, 0 or +1

myInstance1 MyClass;
myInstance2 MyClass;
...
IF (myInstance1 > myInstance2) ...

Öröklődés

CREATE OR REPLACE TYPE MyChildClass UNDER MyClass(   
    myAttribute3 type3, 
    OVERRIDING MEMBER PROCEDURE myProcedure
) 

CREATE OR REPLACE TYPE BODY MyChildClass AS 
    OVERRIDING MEMBER PROCEDURE myProcedure IS 
    BEGIN
        statements;
    END myProcedure;

Absztrakt osztály

CREATE OR REPLACE TYPE MyAbstractClass AS OBJECT (
    myAttribute type,
    NOT INSTANTIABLE NOT FINAL MEMBER PROCEDURE myAbstractprocedure
) NOT INSTANTIABLE NOT FINAL

T-SQL

TODO: elaborate

Adatbázis rendszerek

Az SQL-nek számos konkrét megvalósulása van, melyekhez a gyártól általában saját kezelőt adnak. A legnépszerűbbek az alábbiak:

  • Nehézsúlyú adatbázisok: ezekre jellemző a nagy (gigabájtokban mérhető teleptővel és tíz gigabájtokban mérhető szükséges tárterülettel) méret, sokféle beállítási lehetőség (tehát ezek nem azok a rendszerek, hogy letöltöm a telepítőt, az alapértelmezett beállításokkal vakon feltelepítem, és máris működik), komoly erőforrás igényekkel (5 éves házi laptopra feltenni a legfrissebb változatot alapból felejtős), komoly szakismeret igénnyel (komoly, hosszú, drága tanfolyamokat szerveznek, tehát nem olyan "fél óra alatt átfutom a dokumentációt, és tudom a tudnivaló 95%-át" rendszerek), és persze a fizetős változat igen borsos árával.
    • Oracle: amikor adatbázisra gondolunk, akkor gyakran ez jut eszünkbe; fogalmazhatunk úgy is, hogy ami a telefonoknál az iPhone, az az adatbázisoknál az Oracle. Ill. fordítva: noha az Oracle cégnek számos egyéb terméke van, mégis, magát a céget az adatbázis rendszerével azonosítjuk.
    • Microsoft SQL: ez egy másik nehézsúlyú szereplő az adatbázisok piacán. Az Oracle-lel szemben akár még nyerhet is, mivel egyrészt ennek vannak figyelemre méltó továbbgondolásai (pl. analysis services, data warehouse), valamint az, hogy igen jól integrálódik az Microsoft Azure felhő szolgáltatásába. Ugyanakkor sajnos vannak vele problémák, melyekhez hozzá kell szokni. Ilyen pl. az, hogy nemcsak normál SQL autentikációval lehet bejelentkezni hanem Windows autentikációval is; egészen pontosan kétféle lehetőség van: vagy csak WIndows autentikáció, vagy Windows autentikáció és SQL egyszerre. Az alapértelmezett viszont a csak Windows autentikáció; erre figyelni kell.
  • Középsúlyú adatbázisok: ezek azok az adatbázisok, amelyek ingyenesek (legalábbis házi használatra ill. egyszerűbb célokra mindenképp), a méretük közepes (mondjuk 100 MB nagyságrendű), telepítésük általában egyszerű (a telepítő letöltését és alapértelmezett feltelepítését követően nagyjából úgy fut, ahogy azt szeretnénk), jól átláthatóak (ide nem kell drága tanfolyam, hogy belerázódjunk), erőforrás igényük nem túl nagy (nyugodtan feltelepíthetjük az 5 éves laptopunkra is).
    • MySQL
    • MariaDB: amikor a MySQL-t felvásárolta az Oracle, sokan féltek, hogy az ingyenes konkurenciát egyszerűen megszünteti, vagy legalábbis olyan irányba változtatja, hogy elveszítse vonzerejét. Ők az eredeti kódbázist felhasználva fejlesztették tovább a MySQL-t, MariaDB néven. (Azt gondolom egyébként, hogy a MySQL ugyanúgy használható továbbra is mint korábban, de a MariaDB is megfelelő.)
    • PostgreSQL
  • Pehelysúlyú adatbázisok: ezekre jellemző a minimális méret (pár megabájt), az egyszerű telepíthetőség, valamint lehetőség arra, hogy az adatok pusztán memóriában létezzenek. Ez utóbbi miatt nagyon jól használhatóak oktatási céllal, a különböző adatbázis műveletek kipróbálására, lényegében anélkül, hogy adatbázist kelljen telepíteni.
    • H2
    • Derby
    • HSQLDB

Az adatbázis rendszerek továbbgondolásai

A relációs adatbázis sok esetben nem eléggé hatékony, emiatt számos, kisebb-nagyobb népszerűségű továbbgondolása történt; ebben a részben ezekből szemezgetünk.

NoSQL

MongoDB

JCR

DWH

SSAS

Az SSAS a Microsoft SQL Server Analysis Services rövidítése, tehát egy Microsoft megoldásról van szó. Az alap probléma, melyre megoldást nyújt, az alábbi:

  • Van egy (esetleg több) tényeket (angolul fact) tartalmazó tábla. Ez általában nagy, és többnyire folyamatosan növekszik. Egy példa: internetes eladások.
  • Vannak dimenziókat (angolul is dimension) tartalmazó táblák, melyek általában csillagszerű elrendezésben kapcsolódnak a tény táblához vagy táblákhoz. A fenti példát folytatva: ilyen lehet például a vásárolt termék egyéb adatai, a vásárló személyével kapcsolatos adatok (pl. hol lakik), vagy mondjuk az eladás időpontja.
  • A tény táblákon alapuló, különböző dimenziók mentén összegzett mértékeket (angolul measure) szeretnénk kiszámolni, például hogy országra és negyedévre lebontva melyik termék kategóriából összesen mennyi értékesítettek, vagy mekkora volt a legnagyobb értékű értékesítés.
  • A mértékeket tovább gondolva: fő teljesítménymutatókat (angolul Key Performance Indicator, gyakori rövidítéssel KPI) hozhatunk létre. Az eladási példát folytatva: tegyük fel, hogy az eladás tábla (vagy valamelyik kapcsoló táblája) az előállítási költséget is tartalmazza, melynek segítségével meg tudjuk határozni a nyereséget, tehát pl. azt, hogy az eladási ár hány százaléka a nyereség. Meghatározhatunk cél értéket, valamint piros (rossz), sárga (elfogadható) és zöld (jó) értékeket. A fenti összegzésben nem az abszolút értékekre vagyunk kíváncsiak, hanem a KPI értékekre.

Az SSAS fő feladata ezek biztosítása. Noha mindez megvalósítható normál SQL lekérdezésekkel is, annak számos hátránya van az SSAS-szel szemben:

  • Az adat, amiből az SSAS "táplálkozik", általában egyfajta konszolidált nyers adat, tehát olyan, ami tipikusan túl sok adatot tartalmaz. Az SSAS leszűkíti az adatmennyiséget, ideális esetben annyira, hogy a kliens csak annyi információt kapjon, ami feltétlenül szükséges.
  • Az SSAS több adatforrásból is táplálkozhat, pl. adatbázisból és Excel táblákból egyszerre.
  • A fenti említett mértékek jó része (pl. összegzés, maximum stb.) része az SSAS-nek, és továbbiakat is létre tudunk hozni.
  • Új számított oszlopot adhatunk a táblázathoz.
  • Az SSAS-ben az adatok a memóriában vannak, így sokkal gyorsabb a lekérdezés.
  • Az SSAS üzemeltetése általában olcsóbb mint egy adatáruházé.

Az SSAS-nek viszont számos hátránya is van: elég hosszú a betanulási görbe, összetettek a folyamatok, számos hiba van benne, és kevesen értenek hozzá.

A Microsoft SQL Server telepítő része. Kétféle módon lehet telepíteni az SSAS-t:

  • Multidimenziós: ez volt előbb. Fő fogalma a kocka (cube), ami tények, dimenziók és mértékek halmazát jelenti. A lekérdezési nyelve az MDX, ami az SQL-ből nőtte ki magát.
  • Táblázatos: célja az, hogy az informatikához, azon belül az Excelhez értő, ám nem programozó gazdasági emberek felé nyisson. A lekérdező nyelve a DAX, ami az Excel függvényekre hasonlít.

Az adatok feltöltését (tehát amikor az adatforrásból az SSAS-be kerül az adat) processzálásnak hívjuk. A dimenzió táblákat általában egyszerre processzáljuk, a tény táblákat pedig lehet particionálni, pl. egy partíció tartalmazhat egy hónapnyi adatot.

A processzálás általában drága művelet, hosszú ideig tart, és komoly az erőforrás igénye. Elkerülhető a közvetlen lekérés (DirectQuery) technológiával; ez esetben az SSAS csak átfordítja a bejövő kérést az adatforrás felé. Előnye, hogy nem kell processzálni, nem kell a memóriában tárolni semmilyen adatot, és a végfelhasználó mindig a legújabb adatokat látja. Ez viszont lassú, nagyobb adatbázisok esetén elfogadhatatlanul lassú reakcióidőt eredményez.

Létezik egy köztes mód is: az inkrementális processzálás, amikor gyakran (pl. 10-15 percenként) processzáljuk a különbözetet. Tehát azzal, hogy csak 10-15 percnyi adatot kell feltölteni, az erőforrásban is elfogadható, és a felhasználó is közel valós idejű adatokat kap. Persze mind mindennek, ennek is meg van az ára: nem szabad számolt oszlopot használni (legalábbis a tény táblán), mert az minden processzálás után teljes egészében újraszámolódik.

Vonatkozó szoftverek:

  • Amint azt fent már említettem, a Microsoft SQL server része.
  • A Microsoft SQL Server Management Studio (SSMS) segítségével tudunk hozzá csatlakozni lekérdezéseket végrehajtani.
  • Fejleszteni a Microsoft Visual Studio segítségével lehet, ha feltelepítjük hozzá az SQL Server Data Tools (SSDT) kiegészítőt. (A tapasztalatom az, hogy azzal a kiegészítővel problémák voltak, viszont maga a kiegészítő felkínálja, hogy feltelepítsen egy Visual Studio-t is; azzal működött.)
  • A végeredményt lekérdezni - legalábbis tesztelési céllal - az Excel-lel lehetséges és érdemes. (Ehhez telepíteni kell a kliens könyvtárakat; keressünk rá arra, hogy SSAS client libraries.)
  • Az adatokat olyan üzleti intelligencia eszközzel érdemes megjeleníteni, mint pl. a PowerBI.

MDX

TODO: kidolgozni

DAX

TODO: kidolgozni

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License