Selectați (SQL) - Select (SQL)
Instrucțiunea SQL SELECT returnează un set de rezultate de înregistrări, de la unul sau mai multe tabele .
O instrucțiune SELECT recuperează zero sau mai multe rânduri de la una sau mai multe tabele de baze de date sau vizualizări ale bazei de date . În majoritatea aplicațiilor, SELECT
este cea mai frecvent utilizată comandă de limbaj de manipulare a datelor (DML). Deoarece SQL este un limbaj de programare declarativ , SELECT
interogările specifică un set de rezultate, dar nu specifică cum să se calculeze. Baza de date traduce interogarea într-un „ plan de interogare ” care poate varia între execuții, versiunile bazei de date și software-ul bazei de date. Această funcționalitate se numește „ optimizator de interogare ”, deoarece este responsabilă pentru găsirea celui mai bun plan de execuție posibil pentru interogare, în limitele aplicabile.
Instrucțiunea SELECT are multe clauze opționale:
-
SELECT
clauza este lista de coloane sau expresii SQL care trebuie returnate de interogare. Aceasta este aproximativ operația de proiecție algebră relațională . -
AS
oferă opțional un alias pentru fiecare coloană sau expresie dinSELECT
clauză. Aceasta este operația de redenumire a algebrei relaționale . -
FROM
specifică din ce tabel să obțineți datele. -
WHERE
specifică ce rânduri să recupereze. Aceasta este aproximativ operația de selectare a algebrei relaționale . -
GROUP BY
grupează rânduri care partajează o proprietate, astfel încât o funcție agregată să poată fi aplicată fiecărui grup. -
HAVING
selectează dintre grupurile definite de clauza GROUP BY. -
ORDER BY
specifică modul de comandare a rândurilor returnate.
Prezentare generală
SELECT
este cea mai comună operație în SQL, numită „interogarea”. SELECT
preia date de pe unul sau mai multe tabele sau expresii. SELECT
Declarațiile standard nu au efecte persistente asupra bazei de date. Unele implementări non-standard ale SELECT
pot avea efecte persistente, cum ar fi SELECT INTO
sintaxa furnizată în unele baze de date.
Interogările permit utilizatorului să descrie datele dorite, lăsând sistemul de gestionare a bazelor de date (SGBD) să efectueze planificarea , optimizarea și efectuarea operațiunilor fizice necesare pentru a produce acel rezultat după cum alege.
O interogare include o listă de coloane de inclus în rezultatul final, în mod normal imediat după SELECT
cuvântul cheie. Un asterisc (" *
") poate fi utilizat pentru a specifica că interogarea ar trebui să returneze toate coloanele tabelelor interogate. SELECT
este cea mai complexă afirmație din SQL, cu cuvinte cheie și clauze opționale care includ:
FROM
Clauza, care indică masa (e) pentru a prelua date de la.FROM
Clauza poate include opționalJOIN
subclauze pentru a specifica regulile de aderare la tabele.WHERE
Clauza include un predicat comparație, care limitează rândurile returnate de interogare.WHERE
Clauza elimină toate rândurile din setul de rezultate în cazul în care predicatul comparație nu se evaluează la True.- Cele
GROUP BY
proiecte Clauza de rânduri având valori comune într - un set mai mic de rânduri.GROUP BY
este adesea utilizat împreună cu funcțiile de agregare SQL sau pentru a elimina rândurile duplicate dintr-un set de rezultate.WHERE
Clauza se aplică înainte deGROUP BY
clauza. HAVING
Clauza include un predicat utilizat pentru rândurile de filtrare care rezultă dinGROUP BY
clauza. Deoarece acționează asupra rezultatelorGROUP BY
clauzei, funcțiile de agregare pot fi utilizate înHAVING
predicatul clauzei.- Cele
ORDER BY
Clauza care identifică o coloană [s] pentru a utiliza pentru a sorta datele rezultate, și în care direcția lor (crescătoare sau descrescătoare) sortați. Fără oORDER BY
clauză, ordinea rândurilor returnate de o interogare SQL este nedefinită. - Cuvântul
DISTINCT
cheie elimină datele duplicate.
Următorul exemplu de SELECT
interogare returnează o listă de cărți scumpe. Interogarea preia toate rândurile din tabelul Carte în care coloana preț conține o valoare mai mare de 100,00. Rezultatul este sortat în ordine crescătoare după titlu . Asteriscul (*) din lista de selectare indică faptul că toate coloanele din tabelul Carte ar trebui incluse în setul de rezultate.
SELECT *
FROM Book
WHERE price > 100.00
ORDER BY title;
Exemplul de mai jos demonstrează o interogare a mai multor tabele, grupare și agregare, prin returnarea unei liste de cărți și a numărului de autori asociați cu fiecare carte.
SELECT Book.title AS Title,
count(*) AS Authors
FROM Book
JOIN Book_author
ON Book.isbn = Book_author.isbn
GROUP BY Book.title;
Exemplul de ieșire seamănă cu următorul:
Title Authors ---------------------- ------- SQL Examples and Guide 4 The Joy of SQL 1 An Introduction to SQL 2 Pitfalls of SQL 1
În condiția prealabilă, isbn este singurul nume de coloană comun al celor două tabele și că o coloană numită titlu există doar în tabelul Book , s-ar putea rescrie interogarea de mai sus în următoarea formă:
SELECT title,
count(*) AS Authors
FROM Book
NATURAL JOIN Book_author
GROUP BY title;
Cu toate acestea, mulți furnizori fie nu acceptă această abordare, fie necesită anumite convenții de denumire a coloanelor pentru ca îmbinările naturale să funcționeze eficient.
SQL include operatori și funcții pentru calcularea valorilor pe valorile stocate. SQL permite utilizarea expresiilor din lista de selectare pentru a proiecta date, ca în exemplul următor, care returnează o listă de cărți care costă mai mult de 100,00 cu o coloană suplimentară sales_tax care conține o cifră a impozitului pe vânzări calculată la 6% din preț .
SELECT isbn,
title,
price,
price * 0.06 AS sales_tax
FROM Book
WHERE price > 100.00
ORDER BY title;
Subcercări
Interogările pot fi imbricate astfel încât rezultatele unei interogări să poată fi utilizate într-o altă interogare printr-un operator relațional sau o funcție de agregare. O interogare imbricată este cunoscută și ca subinterogare . În timp ce îmbinările și alte operații de tabel oferă alternative superioare din punct de vedere al calculului (adică mai rapide) în multe cazuri, utilizarea subconsultărilor introduce o ierarhie în execuție care poate fi utilă sau necesară. În exemplul următor, funcția de agregare AVG
primește ca intrare rezultatul unei interogări:
SELECT isbn,
title,
price
FROM Book
WHERE price < (SELECT AVG(price) FROM Book)
ORDER BY title;
O subinterogare poate utiliza valori din interogarea externă, caz în care este cunoscută ca subinterogare corelată .
Din 1999 standardul SQL permite subinterogări denumite expresii de tabel comune (denumite și proiectate după implementarea IBM DB2 versiunea 2; Oracle numește aceste subquery factoring ). CTE-urile pot fi, de asemenea, recursive referindu-se la ele însele; mecanismul rezultat permite traversarea arborelui sau a graficului (atunci când este reprezentată ca relații) și, în general, calcule punct fix .
Masă derivată
Un tabel derivat este utilizarea referințării unei subinterogări SQL într-o clauză FROM. În esență, tabelul derivat este o subinterogare care poate fi selectată din sau alăturată. Funcționalitatea tabelului derivat permite utilizatorului să facă referire la subinterogare ca tabel. Tabelul derivat este, de asemenea, denumit vizualizare inline sau selectare din listă .
În exemplul următor, instrucțiunea SQL implică o asociere de la tabelul inițial Cărți la tabelul derivat „Vânzări”. Acest tabel derivat captează informații despre vânzările de cărți asociate folosind codul ISBN pentru a se alătura tabelului Cărți. Ca rezultat, tabelul derivat oferă setul de rezultate cu coloane suplimentare (numărul de articole vândute și compania care a vândut cărțile):
SELECT b.isbn, b.title, b.price, sales.items_sold, sales.company_nm
FROM Book b
JOIN (SELECT SUM(Items_Sold) Items_Sold, Company_Nm, ISBN
FROM Book_Sales
GROUP BY Company_Nm, ISBN) sales
ON sales.isbn = b.isbn
Exemple
Tabelul "T" | Interogare | Rezultat | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
SELECT * FROM T;
|
|
||||||||||||
|
SELECT C1 FROM T;
|
|
||||||||||||
|
SELECT * FROM T WHERE C1 = 1;
|
|
||||||||||||
|
SELECT * FROM T ORDER BY C1 DESC;
|
|
||||||||||||
nu exista |
SELECT 1+1, 3*2;
|
|
Având în vedere un tabel T, interogarea va avea ca rezultat afișarea tuturor elementelor din toate rândurile tabelului.
SELECT * FROM T
Cu același tabel, interogarea va avea ca rezultat afișarea elementelor din coloana C1 a tuturor rândurilor din tabel. Acest lucru este similar cu o proiecție în algebră relațională , cu excepția faptului că, în cazul general, rezultatul poate conține rânduri duplicate. Acest lucru este, de asemenea, cunoscut sub numele de partiție verticală în unii termeni de bază de date, restricționând ieșirea interogării pentru a vizualiza doar câmpurile sau coloanele specificate.
SELECT C1 FROM T
Cu același tabel, interogarea va duce la afișarea tuturor elementelor tuturor rândurilor în care valoarea coloanei C1 este „1” - în termeni de algebră relațională , se va efectua o selecție , din cauza clauzei WHERE. Aceasta este, de asemenea, cunoscută sub numele de partiție orizontală, restricționând rândurile de ieșire printr-o interogare în funcție de condițiile specificate.
SELECT * FROM T WHERE C1 = 1
Cu mai multe tabele, setul de rezultate va fi fiecare combinație de rânduri. Deci, dacă două tabele sunt T1 și T2, va rezulta fiecare combinație de rânduri T1 cu fiecare rând T2. De exemplu, dacă T1 are 3 rânduri și T2 are 5 rânduri, atunci vor rezulta 15 rânduri.
SELECT * FROM T1, T2
Deși nu este în standard, majoritatea SGBD permite utilizarea unei clauze select fără un tabel, pretinzând că se folosește un tabel imaginar cu un rând. Aceasta este utilizată în principal pentru a efectua calcule în cazul în care un tabel nu este necesar.
Clauza SELECT specifică o listă de proprietăți (coloane) după nume sau caracterul comod („*”) pentru a însemna „toate proprietățile”.
Limitarea rândurilor de rezultate
Adesea este convenabil să indicați un număr maxim de rânduri care sunt returnate. Aceasta poate fi utilizată pentru testare sau pentru a preveni consumul de resurse excesive dacă interogarea returnează mai multe informații decât se aștepta. Abordarea de a face acest lucru variază adesea în funcție de furnizor.
În ISO SQL: 2003 , seturile de rezultate pot fi limitate prin utilizarea
- cursoare sau
- prin adăugarea unei funcții de fereastră SQL la instrucțiunea SELECT
ISO SQL: 2008 a introdus FETCH FIRST
clauza.
Conform documentației PostgreSQL v.9, o funcție de fereastră SQL „efectuează un calcul pe un set de rânduri de tabele care sunt cumva legate de rândul curent”, într-un mod similar cu funcțiile agregate. Numele amintește funcțiile ferestrei de procesare a semnalului . Un apel funcție fereastră conține întotdeauna o clauză OVER .
Funcția fereastră ROW_NUMBER ()
ROW_NUMBER() OVER
poate fi folosit pentru un tabel simplu pe rândurile returnate, de exemplu pentru a returna cel mult zece rânduri:
SELECT * FROM
( SELECT
ROW_NUMBER() OVER (ORDER BY sort_key ASC) AS row_number,
columns
FROM tablename
) AS foo
WHERE row_number <= 10
ROW_NUMBER poate fi nedeterminist : dacă sort_key nu este unic, de fiecare dată când executați interogarea este posibil să obțineți numere de rând diferite atribuite oricărui rând în care sort_key este același. Când sort_key este unic, fiecare rând va primi întotdeauna un număr unic de rând.
Funcția de fereastră RANK ()
Funcția de RANK() OVER
fereastră acționează ca ROW_NUMBER, dar poate reveni mai mult sau mai puțin de n rânduri în caz de condiții de egalitate, de exemplu pentru a returna primii 10 tineri:
SELECT * FROM (
SELECT
RANK() OVER (ORDER BY age ASC) AS ranking,
person_id,
person_name,
age
FROM person
) AS foo
WHERE ranking <= 10
Codul de mai sus ar putea returna mai mult de zece rânduri, de exemplu, dacă există două persoane de aceeași vârstă, ar putea returna unsprezece rânduri.
Clauza FETCH FIRST
Întrucât limitele rezultatelor ISO SQL: 2008 pot fi specificate ca în exemplul următor folosind FETCH FIRST
clauza.
SELECT * FROM T
FETCH FIRST 10 ROWS ONLY
Această clauză este acceptată în prezent de CA DATACOM / DB 11, IBM DB2, SAP SQL Anywhere, PostgreSQL, EffiProz, H2, HSQLDB versiunea 2.0, Oracle 12c și Mimer SQL .
Microsoft SQL Server 2008 și versiuni superioare acceptăFETCH FIRST
, dar este considerat parte a ORDER BY
clauzei. De ORDER BY
, OFFSET
și FETCH FIRST
clauzele sunt toate necesare pentru această utilizare.
SELECT * FROM T
ORDER BY acolumn DESC OFFSET 0 ROWS FETCH FIRST 10 ROWS ONLY
Sintaxă nestandardizată
Unele SGBD oferă sintaxă non-standard fie în locul, fie în plus față de sintaxa standard SQL. Mai jos, sunt enumerate variantele interogării limită simple pentru diferite DBMS-uri:
SET ROWCOUNT 10
SELECT * FROM T
|
MS SQL Server (Acest lucru funcționează și pe Microsoft SQL Server 6.5, în timp ce Selectați top 10 * din T nu) |
SELECT * FROM T
LIMIT 10 OFFSET 20
|
Netezza , MySQL , MariaDB , SAP SQL Anywhere , PostgreSQL (suportă și standardul, de la versiunea 8.4), SQLite , HSQLDB , H2 , Vertica , Polyhedra , Couchbase Server , Snowflake Computing , OpenLink Virtuoso |
SELECT * from T
WHERE ROWNUM <= 10
|
Oracol |
SELECT FIRST 10 * from T
|
Ingres |
SELECT FIRST 10 * FROM T order by a
|
Informix |
SELECT SKIP 20 FIRST 10 * FROM T order by c, d
|
Informix (numerele rândurilor sunt filtrate după evaluarea comenzii după. Clauza SKIP a fost introdusă într-un fixpack v10.00.xC4) |
SELECT TOP 10 * FROM T
|
MS SQL Server , SAP ASE , MS Access , SAP IQ , Teradata |
SELECT * FROM T
SAMPLE 10
|
Teradata |
SELECT TOP 20, 10 * FROM T
|
OpenLink Virtuoso (omite 20, livrează următoarele 10) |
SELECT TOP 10 START AT 20 * FROM T
|
SAP SQL Anywhere (acceptă și standardul, de la versiunea 9.0.1) |
SELECT FIRST 10 SKIP 20 * FROM T
|
Firebird |
SELECT * FROM T
ROWS 20 TO 30
|
Firebird (de la versiunea 2.1) |
SELECT * FROM T
WHERE ID_T > 10 FETCH FIRST 10 ROWS ONLY
|
DB2 |
SELECT * FROM T
WHERE ID_T > 20 FETCH FIRST 10 ROWS ONLY
|
DB2 (rândurile noi sunt filtrate după compararea cu coloana cheie a tabelului T) |
Paginarea rândurilor
Paginarea rândurilor este o abordare utilizată pentru a limita și afișa doar o parte din datele totale ale unei interogări în baza de date. În loc să afișeze sute sau mii de rânduri în același timp, serverului i se solicită o singură pagină (un set limitat de rânduri, de exemplu doar 10 rânduri), iar utilizatorul începe să navigheze solicitând pagina următoare și apoi următoarea , si asa mai departe. Este foarte util, în special în sistemele web, unde nu există o conexiune dedicată între client și server, astfel încât clientul nu trebuie să aștepte să citească și să afișeze toate rândurile serverului.
Abordarea datelor în paginare
-
{rows}
= Numărul de rânduri dintr-o pagină -
{page_number}
= Numărul paginii curente -
{begin_base_0}
= Numărul rândului - 1 de unde începe pagina = (page_number-1) * rânduri
Cea mai simplă metodă (dar foarte ineficientă)
- Selectați toate rândurile din baza de date
- Citiți toate rândurile, dar trimiteți la afișare numai atunci când numărul_ rând al rândurilor citite este între
{begin_base_0 + 1}
și{begin_base_0 + rows}
Select *
from {table}
order by {unique_key}
Altă metodă simplă (puțin mai eficientă decât citirea tuturor rândurilor)
- Selectați toate rândurile de la începutul tabelului până la ultimul rând de afișat (
{begin_base_0 + rows}
) - Citiți
{begin_base_0 + rows}
rândurile, dar trimiteți la afișare numai atunci când numărul_rând al rândurilor citite este mai mare decât{begin_base_0}
SQL | Dialect |
---|---|
select *
from {table}
order by {unique_key}
FETCH FIRST {begin_base_0 + rows} ROWS ONLY
|
SQL ANSI 2008 PostgreSQL SQL Server 2012 Derby Oracle 12c DB2 12 Mimer SQL |
Select *
from {table}
order by {unique_key}
LIMIT {begin_base_0 + rows}
|
MySQL SQLite |
Select TOP {begin_base_0 + rows} *
from {table}
order by {unique_key}
|
SQL Server 2005 |
SET ROWCOUNT {begin_base_0 + rows}
Select *
from {table}
order by {unique_key}
SET ROWCOUNT 0
|
Sybase, SQL Server 2000 |
Select *
FROM (
SELECT *
FROM {table}
ORDER BY {unique_key}
) a
where rownum <= {begin_base_0 + rows}
|
Oracle 11 |
Metoda cu poziționare
- Selectați numai
{rows}
rândurile începând cu rândul următor pentru a afișa ({begin_base_0 + 1}
) - Citiți și trimiteți pentru a afișa toate rândurile citite din baza de date
SQL | Dialect |
---|---|
Select *
from {table}
order by {unique_key}
OFFSET {begin_base_0} ROWS
FETCH NEXT {rows} ROWS ONLY
|
SQL ANSI 2008 PostgreSQL SQL Server 2012 Derby Oracle 12c DB2 12 Mimer SQL |
Select *
from {table}
order by {unique_key}
LIMIT {rows} OFFSET {begin_base_0}
|
MySQL MariaDB PostgreSQL SQLite |
Select *
from {table}
order by {unique_key}
LIMIT {begin_base_0}, {rows}
|
MySQL MariaDB SQLite |
Select TOP {begin_base_0 + rows}
*, _offset=identity(10)
into #temp
from {table}
ORDER BY {unique_key}
select * from #temp where _offset > {begin_base_0}
DROP TABLE #temp
|
Sybase 12.5.3: |
SET ROWCOUNT {begin_base_0 + rows}
select *, _offset=identity(10)
into #temp
from {table}
ORDER BY {unique_key}
select * from #temp where _offset > {begin_base_0}
DROP TABLE #temp
SET ROWCOUNT 0
|
Sybase 12.5.2: |
select TOP {rows} *
from (
select *, ROW_NUMBER() over (order by {unique_key}) as _offset
from {table}
) xx
where _offset > {begin_base_0}
|
SQL Server 2005 |
SET ROWCOUNT {begin_base_0 + rows}
select *, _offset=identity(int,1,1)
into #temp
from {table}
ORDER BY {unique-key}
select * from #temp where _offset > {begin_base_0}
DROP TABLE #temp
SET ROWCOUNT 0
|
SQL Server 2000 |
SELECT * FROM (
SELECT rownum-1 as _offset, a.*
FROM(
SELECT *
FROM {table}
ORDER BY {unique_key}
) a
WHERE rownum <= {begin_base_0 + cant_regs}
)
WHERE _offset >= {begin_base_0}
|
Oracle 11 |
Metoda cu filtru (este mai sofisticată, dar necesară pentru setul de date foarte mare)
- Selectați numai apoi
{rows}
rândurile cu filtru:- Prima pagină: selectați numai primele
{rows}
rânduri, în funcție de tipul bazei de date - Pagina următoare: selectați numai primele
{rows}
rânduri, în funcție de tipul bazei de date, unde{unique_key}
este mai mare decât{last_val}
(valoarea{unique_key}
ultimului rând din pagina curentă) - Pagina anterioară: sortați datele în ordine inversă, selectați numai primele
{rows}
rânduri, unde{unique_key}
este mai mic decât{first_val}
(valoarea{unique_key}
primului rând din pagina curentă) și sortați rezultatul în ordinea corectă
- Prima pagină: selectați numai primele
- Citiți și trimiteți pentru a afișa toate rândurile citite din baza de date
Prima pagina | Pagina următoare | Pagina precedentă | Dialect |
---|---|---|---|
select *
from {table}
order by {unique_key}
FETCH FIRST {rows} ROWS ONLY
|
select *
from {table}
where {unique_key} > {last_val}
order by {unique_key}
FETCH FIRST {rows} ROWS ONLY
|
select *
from (
select *
from {table}
where {unique_key} < {first_val}
order by {unique_key} DESC
FETCH FIRST {rows} ROWS ONLY
) a
order by {unique_key}
|
SQL ANSI 2008 PostgreSQL SQL Server 2012 Derby Oracle 12c DB2 12 Mimer SQL |
select *
from {table}
order by {unique_key}
LIMIT {rows}
|
select *
from {table}
where {unique_key} > {last_val}
order by {unique_key}
LIMIT {rows}
|
select *
from (
select *
from {table}
where {unique_key} < {first_val}
order by {unique_key} DESC
LIMIT {rows}
) a
order by {unique_key}
|
MySQL SQLite |
select TOP {rows} *
from {table}
order by {unique_key}
|
select TOP {rows} *
from {table}
where {unique_key} > {last_val}
order by {unique_key}
|
select *
from (
select TOP {rows} *
from {table}
where {unique_key} < {first_val}
order by {unique_key} DESC
) a
order by {unique_key}
|
SQL Server 2005 |
SET ROWCOUNT {rows}
select *
from {table}
order by {unique_key}
SET ROWCOUNT 0
|
SET ROWCOUNT {rows}
select *
from {table}
where {unique_key} > {last_val}
order by {unique_key}
SET ROWCOUNT 0
|
SET ROWCOUNT {rows}
select *
from (
select *
from {table}
where {unique_key} < {first_val}
order by {unique_key} DESC
) a
order by {unique_key}
SET ROWCOUNT 0
|
Sybase, SQL Server 2000 |
select *
from (
select *
from {table}
order by {unique_key}
) a
where rownum <= {rows}
|
select *
from (
select *
from {table}
where {unique_key} > {last_val}
order by {unique_key}
) a
where rownum <= {rows}
|
select *
from (
select *
from (
select *
from {table}
where {unique_key} < {first_val}
order by {unique_key} DESC
) a1
where rownum <= {rows}
) a2
order by {unique_key}
|
Oracle 11 |
Interogare ierarhică
Unele baze de date oferă sintaxă specializată pentru date ierarhice .
O funcție de fereastră în SQL: 2003 este o funcție agregată aplicată unei partiții a setului de rezultate.
De exemplu,
sum(population) OVER( PARTITION BY city )
calculează suma populațiilor tuturor rândurilor având aceeași valoare de oraș ca rândul curent.
Partițiile sunt specificate folosind clauza OVER care modifică agregatul. Sintaxă:
<OVER_CLAUSE> :: = OVER ( [ PARTITION BY <expr>, ... ] [ ORDER BY <expression> ] )
Clauza OVER poate partiționa și ordona setul de rezultate. Ordinea este utilizată pentru funcții relative la ordine, cum ar fi numărul_rând.
Evaluarea interogării ANSI
Procesarea unei instrucțiuni SELECT conform ANSI SQL ar fi următoarea:
select g.* from users u inner join groups g on g.Userid = u.Userid where u.LastName = 'Smith' and u.FirstName = 'John'
- clauza FROM este evaluată, este realizată o îmbinare încrucișată sau un produs cartezian pentru primele două tabele din clauza FROM rezultând un tabel virtual ca Vtable1
- clauza ON este evaluată pentru vtable1; numai înregistrările care îndeplinesc condiția de asociere g.Userid = u.Userid sunt inserate în Vtable2
- Dacă este specificată o îmbinare exterioară, înregistrările care au fost abandonate din vTable2 sunt adăugate în VTable 3, de exemplu dacă interogarea de mai sus a fost:
toți utilizatorii care nu aparțineau niciunui grup ar fi adăugați înapoi în Vtable3
select u.* from users u left join groups g on g.Userid = u.Userid where u.LastName = 'Smith' and u.FirstName = 'John'
- clauza WHERE este evaluată, în acest caz doar informațiile de grup pentru utilizatorul John Smith ar fi adăugate la vTable4
- se evaluează GRUPUL DE; dacă interogarea de mai sus ar fi:
vTable5 ar consta din membrii returnați din vTable4 aranjați de grupare, în acest caz GroupName
select g.GroupName, count(g.*) as NumberOfMembers from users u inner join groups g on g.Userid = u.Userid group by GroupName
- clauza HAVING este evaluată pentru grupurile pentru care clauza HAVING este adevărată și inserată în vTable6. De exemplu:
select g.GroupName, count(g.*) as NumberOfMembers from users u inner join groups g on g.Userid = u.Userid group by GroupName having count(g.*) > 5
- lista SELECT este evaluată și returnată ca Vtable 7
- se evaluează clauza DISTINCT; rândurile duplicate sunt eliminate și returnate ca Vtable 8
- se evaluează clauza ORDER BY, ordonând rândurile și returnând VCursor9. Acesta este un cursor și nu un tabel, deoarece ANSI definește un cursor ca un set ordonat de rânduri (nu relațional).
Suport funcție fereastră de către furnizorii RDBMS
Implementarea caracteristicilor funcției de fereastră de către furnizorii de baze de date relaționale și motoare SQL diferă foarte mult. Majoritatea bazelor de date acceptă cel puțin o anumită aromă a funcțiilor ferestrei. Cu toate acestea, atunci când analizăm mai atent, devine clar că majoritatea furnizorilor implementează doar un subset al standardului. Să luăm ca exemplu clauza puternică RANGE. Numai Oracle, DB2, Spark / Hive și Google Big Query implementează pe deplin această caracteristică. Mai recent, furnizorii au adăugat noi extensii standardului, de ex. Funcții de agregare a matricei. Acestea sunt deosebit de utile în contextul executării SQL pe un sistem de fișiere distribuite (Hadoop, Spark, Google BigQuery) în care avem garanții de localitate a datelor mai slabe decât într-o bază de date relațională distribuită (MPP). Mai degrabă decât distribuirea uniformă a datelor pe toate nodurile, motoarele SQL care execută interogări împotriva unui sistem de fișiere distribuit pot obține garanții de co-localitate a datelor prin cuibarea datelor și evitând astfel îmbinările potențial costisitoare care implică o amestecare intensă în rețea. Funcțiile agregate definite de utilizator care pot fi utilizate în funcțiile ferestrei sunt o altă caracteristică extrem de puternică.
Generarea de date în T-SQL
Metodă de a genera date bazate pe unirea tuturor
select 1 a, 1 b union all
select 1, 2 union all
select 1, 3 union all
select 2, 1 union all
select 5, 1
SQL Server 2008 acceptă „constructorul de rânduri” specificat în standardul SQL3 („SQL: 1999”)
select *
from (values (1, 1), (1, 2), (1, 3), (2, 1), (5, 1)) as x(a, b)
Referințe
Surse
- Partiționare orizontală și verticală, cărți online Microsoft SQL Server 2000.