Funksionet agregate SQL - SUM, MIN, MAX, AVG, COUNT. Funksioni Sum në SQL: SUM Si të llogarisim shumën sipas kolonës me pyetjen sql

Ky është një tjetër problem i zakonshëm. Parimi bazë është grumbullimi i vlerave të një atributi (elementi agregat) bazuar në renditjen sipas një atributi ose atributi tjetër (elementi i renditjes), mundësisht me seksione rreshtash të përcaktuara bazuar në një atribut ose atribute tjetër (element seksionues). Ka shumë shembuj në jetën reale të llogaritjes së shumave totale, të tilla si llogaritja e bilanceve bankare, mbajtja e shënimeve nëse artikujt janë në magazinë ose shifrat aktuale të shitjeve, etj.

Përpara SQL Server Zgjidhjet e vitit 2012 të bazuara në grupe të përdorura për të llogaritur totalin e ekzekutimit ishin jashtëzakonisht intensive me burime. Prandaj, njerëzit zakonisht u drejtoheshin zgjidhjeve përsëritëse, të cilat ishin të ngadalta, por në disa situata gjithsesi më të shpejta se zgjidhjet e bazuara në grup. Me përmirësimin e mbështetjes së funksionit të dritares në SQL Server 2012, totalet e ekzekutimit mund të llogariten duke përdorur kodin e thjeshtë të bazuar në grup që funksionon shumë më mirë se zgjidhjet më të vjetra të bazuara në T-SQL, të bazuara në grup dhe përsëritës. Mund të tregoj një zgjidhje të re dhe të kaloj në seksionin tjetër; por që ju të kuptoni me të vërtetë shtrirjen e ndryshimit, unë do të përshkruaj mënyrat e vjetra dhe do të krahasoj performancën e tyre me qasjen e re. Natyrisht, ju jeni të lirë të lexoni vetëm pjesën e parë, e cila përshkruan qasjen e re, dhe të kaloni pjesën tjetër të artikullit.

Për demonstrim zgjidhje të ndryshme Do të përdor gjendjen e llogarisë time. Këtu është kodi që krijon dhe plotëson tabelën e Transaksioneve me një sasi të vogël të të dhënave testuese:

AKTIVIZO NO COUNT; PËRDOR TSQL2012; IF OBJECT_ID("dbo.Transactions", "U") NUK ËSHTË NULL HIQ TABELËN dbo.Transactions; KRIJO TABELA dbo.Transaksionet (aktid INT NOT NULL, -- kolona e ndarjes tranid INT NOT NULL, -- kolona e porositjes PARALA NOT NULL, -- matja e KUFIZIMIT PK_Transaksionet ÇELËSI PRIMARY (aktid, tranid)); GO -- test i vogël INSERT INTO dbo.Transaksionet(actid, tranid, val) VLERAT (1, 1, 4.00), (1, 2, -2.00), (1, 3, 5.00), (1, 4, 2.00 ), (1, 5, 1.00), (1, 6, 3.00), (1, 7, -4.00), (1, 8, -1.00), (1, 9, -2.00), (1, 10 , -3.00), (2, 1, 2.00), (2, 2, 1.00), (2, 3, 5.00), (2, 4, 1.00), (2, 5, -5.00), (2, 6 , 4.00), (2, 7, 2.00), (2, 8, -4.00), (2, 9, -5.00), (2, 10, 4.00), (3, 1, -3.00), (3, 2 , 3.00), (3, 3, -2.00), (3, 4, 1.00), (3, 5, 4.00), (3, 6, -1.00), (3, 7, 5.00), (3, 8 , 3,00), (3, 9, 5,00), (3, 10, -3,00);

Çdo rresht i tabelës përfaqëson një transaksion bankar në llogari. Depozitat shënohen si transaksione me vlerë pozitive në kolonën val dhe tërheqjet shënohen si vlerë negative transaksioni. Detyra jonë është të llogarisim gjendjen në llogari në çdo moment të kohës duke grumbulluar shumat e transaksioneve në rreshtin val, të renditura sipas kolonës tranid dhe kjo duhet të bëhet për secilën llogari veç e veç. Rezultati i dëshiruar duhet të duket si ky:

Të dyja zgjidhjet kërkojnë më shumë të dhëna për të testuar. Kjo mund të bëhet me një pyetje si kjo:

DEKLARONI @num_partitions AS INT = 10, @rows_per_partition AS INT = 10000; TRUNCATE TABLE dbo.Transaksionet; INSERT INTO dbo.Transaksionet WITH (TABLOCK) (actid, tranid, val) SELECT NP.n, RPP.n, (ABS(CHECKSUM(NEWID())%2)*2-1) * (1 + ABS(CHECKSUM( NEWID())%5)) NGA dbo.GetNums(1, @num_partitions) AS NP CROSS JOIN dbo.GetNums(1, @rows_per_partition) AS RPP;

Ju mund të vendosni hyrjet tuaja për të ndryshuar numrin e ndarjeve (llogarive) dhe rreshtave (transaksioneve) në një ndarje.

Zgjidhje e bazuar në grup duke përdorur funksionet e dritares

Do të filloj me një zgjidhje të bazuar në grup që përdor funksionin e dritares së grumbullimit SUM. Përkufizimi i dritares këtu është mjaft i qartë: ju duhet të ndani dritaren sipas aktidit, të renditni sipas tranid dhe të filtroni linjat në kornizë nga më e ulta (PËRKUFIZUAR PARAPRAJ) në atë aktuale. Ja kërkesa përkatëse:

ZGJIDH aktid, tranid, val, SHUMË(val) MBI (NDARJE SIPAS aktid RENDITJE NGA RRESHTAT TË PAKUFIZUARA MES RRESHTIT TË PASUR DHE AKTUAL) SI balanca NGA dbo.Transaksionet;

Ky kod jo vetëm që është i thjeshtë dhe i drejtpërdrejtë, por gjithashtu funksionon shpejt. Plani për këtë pyetje është paraqitur në figurë:

Tabela ka një indeks të grupuar që është në përputhje me POC dhe i përdorshëm nga funksionet e dritares. Në mënyrë të veçantë, lista e çelësave të indeksit bazohet në një element ndarës (actid) i ndjekur nga një element i renditjes (tranid), dhe indeksi përfshin gjithashtu të gjitha kolonat e tjera në pyetje (val) për të siguruar mbulim. Plani përmban një kërkim të porositur të ndjekur nga një llogaritje e brendshme e numrit të rreshtit dhe më pas një agregat dritaresh. Meqenëse ekziston një indeks POC, optimizuesi nuk ka nevojë të shtojë një operator renditjeje në plan. Ky është një plan shumë efektiv. Përveç kësaj, ajo shkallëzohet në mënyrë lineare. Më vonë, kur të tregoj rezultatet e krahasimit të performancës, do të shihni se sa më efikase është kjo metodë në krahasim me zgjidhjet e vjetra.

Përpara SQL Server 2012, u përdorën ose nënpyetje ose bashkime. Kur përdorni një pyetje të mbivendosur, totalet e ekzekutimit llogariten duke filtruar të gjitha rreshtat me të njëjtën vlerë aktive si rreshti i jashtëm dhe një vlerë tranid më të vogël ose të barabartë me vlerën në rreshtin e jashtëm. Më pas grumbullimi aplikohet në rreshtat e filtruar. Ja kërkesa përkatëse:

Një qasje e ngjashme mund të zbatohet duke përdorur lidhjet. I njëjti kallëzues përdoret si në klauzolën WHERE të nënpyetjes në klauzolën ON të bashkimit. Në këtë rast, për transaksionin e N-të të së njëjtës llogari A në shembullin e caktuar si T1, do të gjeni N përputhje në shembullin T2, me numrat e transaksionit që shkojnë nga 1 në N. Si rezultat i përputhjes, rreshtat në T1 janë të përsëritura, kështu që ju nevojiten rreshtat e grupit sipas të gjithë elementëve nga T1 për të marrë informacion në lidhje me transaksionin aktual dhe për të aplikuar agregimin në atributin val nga T2 për të llogaritur totalin e ekzekutuar. Kërkesa e plotësuar duket si kjo:

SELECT T1.actid, T1.tranid, T1.val, SUM(T2.val) AS bilanc FROM dbo.Transaksionet AS T1 JOIN dbo.Transaksionet AS T2 ON T2.actid = T1.actid DHE T2.tranid<= T1.tranid GROUP BY T1.actid, T1.tranid, T1.val;

Figura më poshtë tregon planet për të dyja zgjidhjet:

Vini re se në të dyja rastet, një skanim i plotë i indeksit të grupuar kryhet në shembullin T1. Më pas, për çdo rresht në plan, ka një operacion kërkimi në indeksin e fillimit të seksionit të llogarisë rrjedhëse në faqen e fundit të indeksit, duke lexuar të gjitha transaksionet në të cilat T2.tranid është më i vogël ose i barabartë me T1.tranid . Pika ku ndodh grumbullimi i rreshtave është paksa e ndryshme në plane, por numri i rreshtave të lexuar është i njëjtë.

Për të kuptuar se sa rreshta po shikohen, duhet të merret parasysh numri i elementeve të të dhënave. Le të jetë p numri i ndarjeve (llogari) dhe r numri i rreshtave në një ndarje (transaksion). Atëherë numri i rreshtave në tabelë është afërsisht i barabartë me p * r, nëse supozojmë se transaksionet shpërndahen në mënyrë të barabartë midis llogarive. Kështu, skanimi në krye përfshin p*r rreshta. Por mbi të gjitha, ne jemi të interesuar në atë që ndodh në përsëritësin e Nested Loops.

Në çdo seksion, plani parashikon leximin e rreshtave 1 + 2 + ... + r, që në total është (r + r*2) / 2. Numri i përgjithshëm i rreshtave të përpunuara në plane është p*r + p* (r + r2) / 2. Kjo do të thotë që numri i operacioneve në plan rritet në katror me madhësinë e ndarjes, domethënë, nëse e rritni madhësinë e ndarjes me f herë, sasia e punës do të rritet me rreth f 2 herë. Kjo është e keqe. Për shembull, 100 rreshta korrespondojnë me 10 mijë rreshta, dhe një mijë rreshta korrespondojnë me një milion, e kështu me radhë. E thënë thjesht, kjo çon në një ngadalësim të fortë në ekzekutimin e pyetjeve me një madhësi mjaft të madhe të seksionit, sepse funksioni kuadratik rritet shumë shpejt. Zgjidhje të tilla funksionojnë në mënyrë të kënaqshme për disa dhjetëra rreshta për seksion, por jo më shumë.

Zgjidhjet e kursorit

Zgjidhjet e bazuara në kursor zbatohen drejtpërdrejt. Një kursor deklarohet bazuar në një pyetje që rendit të dhënat sipas aktid dhe tranid. Pas kësaj, kryhet një kalim përsëritës i regjistrimeve të kursorit. Kur gjendet një numërim i ri, ndryshorja që përmban agregatin rivendoset. Në çdo përsëritje, shuma e transaksionit të ri i shtohet variablit, pas së cilës rreshti ruhet në një variabël tabele me informacion rreth transaksionit aktual plus vlerën aktuale të totalit të ekzekutuar. Pas kalimit të përsëritjes, rezultati nga ndryshorja e tabelës kthehet. Këtu është kodi për zgjidhjen e përfunduar:

DEKLAROJ @Rezultatin SI TABELA (actid INT, tranid INT, val MONEY, balance MONEY); DEKLARONI @actid SI INT, @prvactid AS INT, @tranid AS INT, @val SI PARA, @balance SI PARA; DEKLARONI C KURSORIN FAST_PERWARD FOR SELECT actid, tranid, val FROM dbo.Transaksionet RENDOSJE NGA aktid, tranid; HAPE C FETCH TJETËR NGA C NË @actid, @tranid, @val; SELECT @prvactid = @actid, @balance = 0; NDERSA @@fetch_status = 0 FILLO NESE @actid<>@prvactid SELECT @prvactid = @actid, @balance = 0; SET @balance = @balance + @val; INSERT INTO @Result VALUES(@actid, @tranid, @val, @balance); MERRNI TJETËR NGA C NË @actid, @tranid, @val; FUNDI MBYLL C; DEALLOKATE C; ZGJIDH * NGA @Rezultati;

Plani i pyetjes duke përdorur kursorin është paraqitur në figurë:

Ky plan shkallëzohet në mënyrë lineare sepse të dhënat nga indeksi skanohen vetëm një herë në një renditje të caktuar. Gjithashtu, çdo operacion i marrjes së një rreshti nga kursori ka afërsisht të njëjtën kosto për rresht. Nëse marrim ngarkesën e krijuar duke përpunuar një rresht të kursorit të barabartë me g, kostoja e kësaj zgjidhjeje mund të vlerësohet si p * r + p * r * g (mbani mend, p është numri i seksioneve dhe r është numri të rreshtave në seksion). Pra, nëse e rritni numrin e rreshtave për ndarje me f herë, ngarkesa në sistem do të jetë p*r*f + p*r*f*g, domethënë do të rritet në mënyrë lineare. Kostoja e përpunimit për rresht është e lartë, por për shkak të natyrës lineare të shkallëzimit, nga një madhësi e caktuar e ndarjes, kjo zgjidhje do të shkallëzohet më mirë se pyetja e ndërlidhur dhe zgjidhjet e bazuara në bashkim për shkak të shkallëzimit kuadratik të këtyre zgjidhjeve. Matja ime e performancës tregoi se numri i herëve që zgjidhja e kursorit është më e shpejtë është disa qindra rreshta për ndarje.

Pavarësisht përfitimeve të performancës të ofruara nga zgjidhjet e bazuara në kursor, ato në përgjithësi duhet të shmangen sepse nuk janë relacionale.

Zgjidhje të bazuara në CLR

Një zgjidhje e mundshme e bazuar në CLR (Koha e ekzekutimit në gjuhën e zakonshme)është në thelb një formë e zgjidhjes së bazuar në kursor. Dallimi është se në vend që të përdoret një kursor T-SQL, i cili kërkon shumë burime për të marrë rreshtin tjetër dhe për të përsëritur, përdoren përsëritjet .NET SQLDataReader dhe .NET, të cilat janë shumë më të shpejta. Një veçori e CLR që e bën këtë opsion më të shpejtë është se rreshti që rezulton nuk nevojitet në një tabelë të përkohshme - rezultatet dërgohen drejtpërdrejt në procesin e thirrjes. Logjika e zgjidhjes së bazuar në CLR është e ngjashme me logjikën e zgjidhjes së bazuar në kursor dhe T-SQL. Këtu është kodi C# që përcakton procedurën e ruajtur të vendimit:

Përdorimi i Sistemit; duke përdorur System.Data; duke përdorur System.Data.SqlClient; duke përdorur System.Data.SqlTypes; duke përdorur Microsoft.SqlServer.Server; klasa publike e pjesshme StoredProcedures (Banesat e llogarive të pavlefshme statike publike () ( duke përdorur (SqlConnection conn = new SqlConnection ("context connection=true;")) ( SqlCommand comm = new SqlCommand(); comm.Connection = conn; comm.Comman" " + "SELECT actid, tranid, val " + "FROM dbo.Transactions " + "ORDER BY actid, tranid;"; SqlMetaData kolonat = new SqlMetaData; kolonat = new SqlMetaData("actid" , SqlDbType.Int); kolona = reja SqlMetaData("tranid" , SqlDbType.Int); kolonat = SqlMetaData e re ("val" , SqlDbType.Money); kolonat = new SqlMetaData("balanca", SqlDbType.Money); SqlDataRecord rekordi Regjistrohu i ri Sonteqlqum); Pipe.SendResultsStart(rekord); conn.Open();lexuesi SqlDataReader = comm.ExecuteReader();SqlInt32 prvactid = 0;Bilanci i SqlMoney = 0; while (reader.Read()) (SqlInt32 actid(Sql)Int.Get.Get. ;SqlMoney val = reader.GetSqlMoney(2);if (actid == prvactid) (balance += val; ) other (balance = val; ) prvactid = actid;rec ord.SetSqlInt32(0, lexues.GetSqlInt32(0)); rekord.SetSqlInt32(1, lexues.GetSqlInt32(1)); rekord.SetSqlMoney(2, val); rekord.SetSqlMoney(3, bilanc); SqlContext.Pipe.SendResultsRow(record); ) SqlContext.Pipe.SendResultsEnd(); ) ))

Për të qenë në gjendje të ekzekutoni këtë procedurë të ruajtur në SQL Server, së pari duhet të ndërtoni një asamble të quajtur AccountBalances bazuar në këtë kod dhe ta vendosni atë në një bazë të dhënash TSQL2012. Nëse nuk jeni njohur me vendosjen e asambleve në SQL Server, mund të lexoni seksionin "Procedurat e ruajtura" dhe "Koha e ekzekutimit të gjuhës së zakonshme" në artikullin "Procedurat e ruajtura".

Nëse e keni emërtuar asamblenë AccountBalances dhe rruga për në skedarin e montimit është "C:\Projects\AccountBalances\bin\Debug\AccountBalances.dll", mund ta ngarkoni asamblenë në bazën e të dhënave dhe të regjistroni procedurën e ruajtur me kodin e mëposhtëm:

CREATE AccountBalances ASSEMBLY NGA "C:\Projects\AccountBalances\bin\Debug\AccountBalances.dll"; SHKO KRIJO PROCEDURËN dbo.AccountBalances SI EMRI I JASHTËM AccountBalances.StoredProcedures.AccountBalances;

Pasi të vendoset asambleja dhe të regjistrohet procedura, mund ta ekzekutoni me kodin e mëposhtëm:

EXEC dbo.Bilanci i llogarisë;

Siç thashë, SQLDataReader është vetëm një formë tjetër e kursorit, por në këtë version, kostoja e përgjithshme e leximit të rreshtave është shumë më pak se përdorimi i një kursori tradicional në T-SQL. Gjithashtu, në .NET, përsëritjet janë shumë më të shpejta se në T-SQL. Kështu, zgjidhjet e bazuara në CLR gjithashtu shkallëzohen në mënyrë lineare. Testimi ka treguar se performanca e kësaj zgjidhjeje bëhet më e lartë se performanca e zgjidhjeve që përdorin nënpyetje dhe bashkohen kur numri i rreshtave në seksion kalon 15.

Kur të keni mbaruar, ekzekutoni kodin e mëposhtëm të pastrimit:

PROCEDURA E HEQJES dbo.Bilanci i llogarisë; HIQ balancat e llogarisë së ASSEMBLY;

Përsëritjet e mbivendosura

Deri në këtë pikë, unë kam treguar zgjidhje përsëritëse dhe të bazuara në grup. Zgjidhja e mëposhtme bazohet në përsëritjet e mbivendosura, e cila është një hibrid i qasjeve iterative dhe të bazuara në grup. Ideja është që fillimisht të kopjohen rreshtat nga tabela burimore (llogaritë bankare në rastin tonë) në një tabelë të përkohshme, së bashku me një atribut të ri të quajtur rownum, i cili llogaritet duke përdorur funksionin ROW_NUMBER. Numrat e rreshtave ndahen sipas actid dhe renditen sipas tranid, kështu që transaksionit të parë në çdo llogari bankare i caktohet numri 1, transaksionit të dytë i caktohet numri 2, e kështu me radhë. Më pas krijohet një indeks i grupuar me një listë çelësash (rownum, actid) në tabelën e përkohshme. Më pas përdor një CTE rekurzive ose një lak të personalizuar për të përpunuar një rresht për përsëritje në të gjitha numërimet. Totali i ekzekutimit llogaritet më pas duke shtuar vlerën që korrespondon me rreshtin aktual me vlerën e lidhur me rreshtin e mëparshëm. Këtu është një zbatim i kësaj logjike duke përdorur një CTE rekurzive:

SELECT aktid, tranid, val, ROW_NUMRI() MBI (NDARJE NGA aktid RENDOSJE NGA tranid) SI rend INTO #Transactions FROM dbo.Transactions; KRIJO INDEKS UNIK TË GRUPTUAR idx_rownum_actid ON #Transactions(rownum, actid); ME C AS (SELECT 1 AS rownum, actid, tranid, val, val AS sumqty FROM #Transactions WHERE rownum = 1 UNION ALL SELECT PRV.rownum + 1, PRV.actid, CUR.tranid, CUR.val, + PRV.sumqty CUR.val FROM C AS PRV JOIN #Transaksionet AS CUR ON CUR.rownum = PRV.rownum + 1 DHE CUR.actid = PRV.actid) SELECT aktid, tranid, val, shuma NGA C OPTION (MAXREKURSION 0); DOP TABLE #Transaksionet;

Dhe ky është zbatimi duke përdorur një lak të qartë:

ZGJIDH RRESHTIN_NUMBER() MBI (NJESË SIPAS aktid RENDOSJE NGA tranid) AS rownum, actid, tranid, val, CAST(val AS BIGINT) SI shuma INTO #Transactions FROM dbo.Transactions; KRIJO INDEKS UNIK TË GRUPTUAR idx_rownum_actid ON #Transactions(rownum, actid); DEKLAROJE @rownum SI INT; SET @rownum = 1; NDERSA 1 = 1 FILLON SET @rownum = @rownum + 1; PËRDITËSOJE SETIN CUR sumqty = PRV.sumqty + CUR.val FROM #Transactions AS CUR JOIN #Transactions AS PRV ON CUR.rownum = @rownum DHE PRV.rownum = @rownum - 1 DHE CUR.actid = PRV.actid; NËSE @@rowcount = 0 THYER; FUND SELECT aktid, tranid, val, shuma NGA #Transactions; DOP TABLE #Transaksionet;

Kjo zgjidhje siguron performancë të mirë kur ka një numër të madh ndarjesh me një numër të vogël rreshtash në ndarje. Numri i përsëritjeve është më pas i vogël dhe pjesa më e madhe e punës kryhet nga pjesa e zgjidhjes e bazuar në grup, e cila lidh rreshtat e lidhur me një numër rreshti me rreshtat e lidhur me numrin e rreshtit të mëparshëm.

Përditësim me shumë rreshta me variabla

Truket për llogaritjen e totalit të ekzekutimit të treguar deri në këtë pikë janë të garantuara për të dhënë rezultatin e saktë. Metodologjia e përshkruar në këtë seksion është e paqartë sepse bazohet në sjelljen e vëzhguar dhe jo të dokumentuar të sistemit, dhe gjithashtu bie në kundërshtim me parimet e relativitetit. Atraktiviteti i tij i lartë është për shkak të shpejtësisë së lartë të punës.

Kjo metodë përdor një deklaratë UPDATE me variabla. Deklarata UPDATE mund t'i caktojë shprehje variablave bazuar në vlerën e një kolone, dhe gjithashtu mund të caktojë vlera në kolona për një shprehje me një ndryshore. Zgjidhja fillon duke krijuar një tabelë të përkohshme të quajtur Transactions me atributet actid, tranid, val dhe balance, dhe një indeks të grupuar me një listë çelësash (actid, tranid). Tabela e përkohshme më pas plotësohet me të gjitha rreshtat nga baza e të dhënave origjinale të Transaksioneve, me një vlerë prej 0.00 të futur në kolonën e bilancit të të gjitha rreshtave. Më pas thirret një deklaratë UPDATE me variablat e lidhur me tabelën e përkohshme për të llogaritur totalin e ekzekutuar dhe për të futur vlerën e llogaritur në kolonën e bilancit.

Përdoren variablat @prevaccount dhe @prevbalance, dhe vlera në kolonën e bilancit llogaritet duke përdorur shprehjen e mëposhtme:

SET @prevbalance = bilanc = RAST KUR actid = @prevaccount PASTAJ @prevbalance + val ALSE val FUND

Shprehja CASE kontrollon nëse ID-të e llogarive rrjedhëse dhe të mëparshme janë të njëjta dhe, nëse janë të barabarta, kthen shumën e vlerave të mëparshme dhe aktuale në kolonën e bilancit. Nëse ID-të e llogarisë janë të ndryshme, shuma e transaksionit aktual kthehet. Më pas, rezultati i shprehjes CASE futet në kolonën e bilancit dhe i caktohet ndryshores @prevbalance. Në një deklaratë të veçantë, ndryshores ©prevaccount i caktohet identifikuesi i llogarisë rrjedhëse.

Pas deklaratës UPDATE, zgjidhja paraqet rreshtat nga tabela e përkohshme dhe e fshin këtë të fundit. Këtu është kodi për zgjidhjen e përfunduar:

CREATE TABLE #Transactions (actid INT, tranid INT, val MONEY, balance MONEY); KRIJO INDEKS TË GRUPTUAR idx_actid_tranid ON #Transactions(actid, tranid); INSERT INTO #Transactions WITH (TABLOCK) (actid, tranid, val, balance) SELECT actid, tranid, val, 0.00 NGA dbo.Transaksionet RENDOSJE NGA aktid, tranid; DEKLAROJE @prevaccount SI INT, @prevbalance SI PARA; PËRDITËSOJE #Transaksionet SET @prevbalance = bilanci = RAST KUR actid = @prevaccount THEN @prevbalance + val ELSE val FUND, @prevaccount = aktid FROM #Transactions WITH(INDEX(1), TABLOCKX) OPTION (MAXDOP 1); SELECT * FROM #Transactions; DOP TABLE #Transaksionet;

Plani për këtë zgjidhje është paraqitur në figurën e mëposhtme. Pjesa e parë është një deklaratë INSERT, pjesa e dytë është një deklaratë UPDATE dhe pjesa e tretë është një deklaratë SELECT:

Kjo zgjidhje supozon që gjatë optimizimit të ekzekutimit të UPDATE, do të kryhet gjithmonë një skanim i porositur i indeksit të grupuar dhe zgjidhja përfshin një numër sugjerimesh për të parandaluar rrethanat që mund të ndërhyjnë në këtë, si p.sh. Problemi është se nuk ka asnjë garanci zyrtare që optimizuesi do të shikojë gjithmonë në rendin e indeksit të grupuar. Ju nuk mund të mbështeteni në veçoritë e llogaritjes fizike për të siguruar korrektësinë logjike të kodit, përveç nëse ka elementë logjikë në kod që, sipas përkufizimit, mund të garantojnë një sjellje të tillë. Nuk ka veçori logjike në këtë kod që mund të garantojnë pikërisht këtë sjellje. Natyrisht, zgjedhja nëse do ta përdorni apo jo këtë metodë varet tërësisht në ndërgjegjen tuaj. Mendoj se është e papërgjegjshme ta përdorësh, edhe nëse e ke kontrolluar mijëra herë dhe "duket se funksionon ashtu siç duhet".

Për fat të mirë, në SQL Server 2012 kjo zgjedhje bëhet pothuajse e panevojshme. Me një zgjidhje jashtëzakonisht efikase duke përdorur funksionet e grumbullimit me dritare, nuk keni pse të mendoni për zgjidhje të tjera.

matja e performancës

Kam matur dhe krahasuar performancën e teknikave të ndryshme. Rezultatet janë paraqitur në figurat e mëposhtme:

I ndava rezultatet në dy grafikë sepse pyetja e ndërthurur ose metoda e bashkimit është aq e ngadaltë sa që më duhej të përdorja një shkallë të ndryshme për të. Në çdo rast, vini re se shumica e zgjidhjeve tregojnë një lidhje lineare midis sasisë së punës dhe madhësisë së ndarjes, dhe vetëm zgjidhja e bazuar në një pyetje të ndërthurur ose bashkim tregon një marrëdhënie kuadratike. Është gjithashtu e qartë se sa më efikase është zgjidhja e re e bazuar në funksionin e grumbullimit me dritare. Zgjidhja e bazuar në UPDATE me variabla është gjithashtu shumë e shpejtë, por për arsyet e përshkruara tashmë, nuk e rekomandoj përdorimin e saj. Zgjidhja CLR është gjithashtu mjaft e shpejtë, por kërkon që ju të shkruani të gjithë këtë kod .NET dhe të vendosni montimin në bazën e të dhënave. Pavarësisht se si e shikoni, zgjidhja e bazuar në grup duke përdorur agregatët e dritareve mbetet zgjidhja e preferuar.

Si mund të zbuloj numrin e modeleve të PC-ve të prodhuara nga një shitës i caktuar? Si të përcaktohet vlera mesatare e çmimit të kompjuterëve me të njëjtat karakteristika teknike? Këto dhe shumë pyetje të tjera që lidhen me disa informacione statistikore mund të marrin përgjigje me ndihmën e funksionet përmbledhëse (agregate).. Standardi ofron funksionet e mëposhtme agregate:

Të gjitha këto funksione kthejnë një vlerë të vetme. Në të njëjtën kohë, funksionet COUNT, MIN Dhe MAX zbatohen për çdo lloj të dhënash, ndërsa SHUMË Dhe AVG përdoret vetëm për fushat numerike. Dallimi midis funksionit COUNT(*) Dhe COUNT(<имя поля>) është se e dyta nuk merr parasysh vlerat NULL gjatë llogaritjes.

Shembull. Gjeni çmimin minimal dhe maksimal për kompjuterët personalë:

Shembull. Gjeni numrin e disponueshëm të kompjuterëve të prodhuar nga prodhuesi A:

Shembull. Nëse jemi të interesuar për numrin e modeleve të ndryshme të prodhuara nga prodhuesi A, atëherë pyetja mund të formulohet si më poshtë (duke përdorur faktin që secili model është regjistruar një herë në tabelën e produktit):

Shembull. Gjeni numrin e modeleve të ndryshme të disponueshme të prodhuara nga prodhuesi A. Pyetja është e ngjashme me atë të mëparshme, në të cilën kërkohej të përcaktohej numri i përgjithshëm i modeleve të prodhuara nga prodhuesi A. Këtu, kërkohet të gjeni numrin e modeleve të ndryshme në tabelën e PC-së (dmth. në dispozicion për shitje).

Për të siguruar që përdoren vetëm vlera unike gjatë marrjes së treguesve statistikorë, kur argumenti i funksionit agregat mund të përdoret Parametri DISTINCT. Një tjetër parametri ALLështë parazgjedhja dhe pret të numërojë të gjitha vlerat e kthyera në kolonë. Operator,

Nëse duhet të marrim numrin e modeleve të PC-ve të prodhuara nga secili prodhuesi, do t'ju duhet të përdorni GRUP SIPAS ofertës, në mënyrë sintaksore pas KU klauzolat.

GRUP SIPAS ofertës

GRUP SIPAS ofertës përdoret për të përcaktuar grupet e linjave të daljes në të cilat mund të aplikohen funksionet e përgjithshme (COUNT, MIN, MAX, AVG dhe SUM). Nëse kjo klauzolë mungon dhe përdoren funksionet e përgjithshme, atëherë të gjitha kolonat me emrat e përmendur në ZGJIDH, duhet të përfshihet në funksionet agregate, dhe këto funksione do të zbatohen për të gjithë grupin e rreshtave që plotësojnë kallëzuesin e pyetjes. Përndryshe, të gjitha kolonat e listës SELECT, nuk përfshihen në funksione agregate, duhet të specifikohen në klauzolën GROUP BY. Si rezultat, të gjitha rreshtat e daljes së pyetjes ndahen në grupe të karakterizuara nga të njëjtat kombinime vlerash në këto kolona. Pas kësaj, funksionet agregate do të aplikohen për secilin grup. Vini re se për GROUP BY, të gjitha vlerat NULL trajtohen si të barabarta, d.m.th. kur grupohet sipas një fushe që përmban vlera NULL, të gjitha rreshtat e tillë do të bien në një grup.
Nëse nëse ka një klauzolë GROUP BY, në klauzolën SELECT nuk ka funksione agregate, atëherë pyetja thjesht do të kthejë një rresht nga secili grup. Kjo veçori, së bashku me fjalën kyçe DISTINCT, mund të përdoret për të eliminuar rreshtat e dyfishta në një grup rezultatesh.
Konsideroni një shembull të thjeshtë:
SELECT model, COUNT(model) AS Qty_model, AVG(çmim) AS çmim_mesatar
NGA PC
GRUPI SIPAS modelit;

Në këtë pyetje, për çdo model PC, përcaktohet numri i tyre dhe kostoja mesatare. Të gjitha rreshtat me të njëjtin model (numër modeli) formojnë një grup, dhe dalja SELECT llogarit numrin e vlerave dhe çmimet mesatare për secilin grup. Rezultati i pyetjes do të jetë tabela e mëposhtme:
model Sasia_model Çmimi_mesatar
1121 3 850.0
1232 4 425.0
1233 3 843.33333333333337
1260 1 350.0

Nëse do të kishte një kolonë me një datë në SELECT, atëherë do të ishte e mundur të llogariteshin këta tregues për çdo datë specifike. Për ta bërë këtë, duhet të shtoni datën si një kolonë grupimi dhe më pas do të llogariten funksionet e përgjithshme për çdo kombinim vlerash (model-datë).

Ka disa specifike rregullat për ekzekutimin e funksioneve agregate:

  • Nëse si rezultat i kërkesës asnjë rresht nuk është marrë(ose më shumë se një rresht për këtë grup), atëherë nuk ka të dhëna fillestare për llogaritjen e ndonjë prej funksioneve të përgjithshme. Në këtë rast, rezultati i ekzekutimit të funksioneve COUNT do të jetë zero, dhe rezultati i të gjitha funksioneve të tjera do të jetë NULL.
  • Argumenti funksioni agregat vetë nuk mund të përmbajë funksione agregate(funksioni nga funksioni). ato. në një kërkesë është e pamundur, të themi, të marrësh një maksimum vlerash mesatare.
  • Rezultati i ekzekutimit të funksionit COUNT është numër i plotë(SHUMË I PLOTË). Funksionet e tjera agregate trashëgojnë llojet e të dhënave të vlerave të përpunuara.
  • Nëse, gjatë ekzekutimit të funksionit SUM, është marrë një rezultat që ka tejkaluar vlerën maksimale të llojit të të dhënave të përdorur, një gabim.

Pra, nëse kërkesa nuk përmban GROUP BY oferta, pastaj funksionet agregate të përfshira në Klauzola SELECT, ekzekutohen në të gjitha vargjet e pyetjeve që rezultojnë. Nëse kërkesa përmban GRUP SIPAS ofertës, çdo grup rreshtash që ka të njëjtat vlera të kolonës ose grupit të kolonave të specifikuara në oferta GRUP BY, përbën një grup, dhe funksionet agregate kryhet për secilin grup veç e veç.

Duke pasur ofertë

Nëse Klauzola WHERE përcakton një kallëzues për filtrimin e vargut, atëherë Klauzola e PASJES aplikuar pas grupimit për të përcaktuar një grup të ngjashëm filtrues kallëzues sipas vlerave funksionet agregate. Kjo klauzolë është e nevojshme për të vërtetuar vlerat me të cilat janë marrë funksioni agregat jo nga rreshtat e veçantë të burimit të regjistrimit të përcaktuar në Klauzola NGA, dhe nga grupe të linjave të tilla. Prandaj, një kontroll i tillë nuk mund të përfshihet Klauzola WHERE.

Në këtë tutorial, do të mësoni se si ta përdorni Funksioni SUM në SQL Server (Transact-SQL) me sintaksë dhe shembuj.

Përshkrim

Në SQL Server (Transact-SQL) Funksioni SUM kthen vlerën totale të shprehjes.

Sintaksë

Sintaksa për funksionin SUM në SQL Server (Transact-SQL) është:

OSE sintaksa e funksionit SUM kur grupohen rezultatet sipas një ose më shumë kolonave:

Opsione ose Argumente

shprehja1, shprehja2, ... shprehja_n janë shprehje që nuk përfshihen në funksionin SUM dhe duhet të përfshihen në klauzolën GROUP BY në fund të deklaratës SQL.
agregate_expression është kolona ose shprehja që do të përmblidhet.
tabela - tabela nga të cilat dëshironi të merrni shënime. Duhet të ketë të paktën një tabelë të listuar në klauzolën FROM.
Kushtet WHERE - fakultative. Këto janë kushtet që duhet të plotësohen për të dhënat e përzgjedhura.

Aplikacion

Funksioni SUM mund të përdoret në versionet e mëposhtme të SQL Server (Transact-SQL):
SQL Server vNext, SQL Server 2016, SQL Server 2015, SQL Server 2014, SQL Server 2012, SQL Server 2008 R2, SQL Server 2008, SQL Server 2005

Shembull me një fushë të vetme

Le të shohim disa shembuj të funksionit SUM Server SQL për të kuptuar se si të përdoret funksioni SUM në SQL Server (Transact-SQL).

Për shembull, mund të zbuloni se si numri i përgjithshëm i të gjitha produkteve, numri i të cilëve është më i madh se 10.

Në këtë shembull të funksionit SUM, ne kemi emërtuar shprehjen SUM(sasi ) "Sasia totale". Kur ktheni një grup rezultatesh - "Sasia totale" do të shfaqet si emri i fushës.

Shembull i dallueshëm

Ju mund të përdorni deklaratën DISTINCT në funksionin SUM. Për shembull, deklarata SQL më poshtë kthen pagën totale me vlera unike pagash ku paga është më pak se 29,000 dollarë në vit.

Nëse dy paga do të ishin 24,000 dollarë në vit, vetëm një nga ato vlera do të përdorej në funksionin SUM.

Shembull i formulës

Shprehja e përfshirë në funksionin SUM nuk duhet të jetë një fushë e vetme. Ju gjithashtu mund të përdorni një formulë. Për shembull, ju mund të llogarisni komisionin total.

Transaksion SQL

SELECT SUM(shitje * 0.03) AS "Komisioni Total" NGA porositë;

SELECT SUM (shitjet * 0.03 ) AS "Komisioni Total"

NGA porositë ;

GRUPI SIPAS shembullit

Në disa raste, do t'ju duhet të përdorni klauzolën GROUP BY me funksionin SUM.

SQL - Mësimi 11. Funksionet përmbledhëse, kolonat e llogaritura dhe pamjet

Funksionet përfundimtare quhen gjithashtu statistikore, agregate ose përmbledhëse. Këto funksione përpunojnë një grup rreshtash për të numëruar dhe kthyer një vlerë të vetme. Ekzistojnë pesë funksione të tilla:
  • AVG() Funksioni kthen vlerën mesatare të një kolone.

  • COUNT() Funksioni kthen numrin e rreshtave në një kolonë.

  • MAX() Funksioni kthen vlerën më të madhe në një kolonë.

  • MIN() Funksioni kthen vlerën më të vogël në një kolonë.

  • SUM() Funksioni kthen shumën e vlerave të kolonës.

Njërin prej tyre - COUNT() - e kemi takuar tashmë në mësimin 8. Tani le të takojmë pjesën tjetër. Supozoni se donim të dinim çmimin minimal, maksimal dhe mesatar të librave në dyqanin tonë. Pastaj nga tabela Çmimet (çmimet) duhet të merrni vlerat minimale, maksimale dhe mesatare për kolonën e çmimeve. Kërkesa është e thjeshtë:

SELECT MIN(çmimi), MAX(çmimi), AVG(çmimi) FROM çmimet;

Tani duam të kuptojmë se për sa na e ka sjellë furnizuesi "Shtypshkronja" (id=2). Bërja e një kërkese të tillë nuk është e lehtë. Le të mendojmë se si ta bëjmë atë:

1. Së pari, duhet të zgjidhni identifikuesit (id_incoming) të atyre dërgesave që janë kryer nga furnizuesi i "Print House" (id=2) nga tabela Deliveries (incoming):

2. Tani, nga tabela e Ditarit të Furnizimit (revista_hyrëse), duhet të zgjidhni mallrat (id_produkti) dhe sasitë e tyre (sasia), të cilat janë kryer në dërgesat e gjetura në paragrafin 1. Kjo do të thotë, kërkesa nga pika 1 bëhet e ndërthurur:

3. Tani duhet të shtojmë në tabelën që rezulton çmimet për mallrat e gjetura, të cilat ruhen në tabelën Çmimet. Kjo do të thotë, ne duhet të bashkojmë tabelat Ditari i furnizimit (magazine_incoming) dhe Çmimet (çmimet) nga kolona id_product:

4. Në tabelën që rezulton, mungon qartë kolona Sum, d.m.th kolona e llogaritur. Mundësia për të krijuar kolona të tilla ofrohet në MySQL. Për ta bërë këtë, thjesht duhet të specifikoni në pyetje emrin e kolonës së llogaritur dhe çfarë duhet të llogarisë. Në shembullin tonë, një kolonë e tillë do të quhet përmbledhje dhe do të llogarisë produktin e kolonave të sasisë dhe çmimit. Emri i kolonës së re ndahet me fjalën AS:

SELECT magazine_incoming.id_product, magazine_incoming.sasia, Prices.price, magazine_incoming.sasia*prices.price AS përmbledhje FROM magazine_incoming, çmimet WHERE magazine_incoming.id_product= Prices.id_produkti_hyrë AND id_SELECTor_incoming;

5. E shkëlqyeshme, ajo që na mbetet është të përmbledhim kolonën përmbledhëse dhe më në fund të zbulojmë se për sa na e ka sjellë furnitori "Shtypshkronja" mallrat. Sintaksa për përdorimin e funksionit SUM() është si më poshtë:

SELECT SUM(emri_kolona) FROM emri_tabeles;

Ne e dimë emrin e kolonës - summa, por nuk e kemi emrin e tabelës, pasi është rezultat i pyetësorit. Çfarë duhet bërë? Për raste të tilla, MySQL ka Views. Një pamje është një pyetje e zgjedhur që i jepet një emër unik dhe mund të ruhet në një bazë të dhënash për përdorim të mëvonshëm.

Sintaksa për krijimin e një pamjeje është si më poshtë:

KRIJO PARAQIT emrin e_view SI pyetje;

Le ta ruajmë kërkesën tonë si një pamje me emrin report_vendor:

KRIJO PAMJE report_vendor SI ZGJEDHJE magazine_incoming.id_product, magazine_incoming.sasia, Prices.price, Magazine_incoming.sasia*prices.çmimi SI përmbledhje NGA revista_arritëse, çmimet WHERE magazine_incoming. );

6. Tani mund të përdorni funksionin përfundimtar SUM():

ZGJIDH SHUMËN(përmbledhjen) NGA raporti_shitësi;

Këtu kemi arritur rezultatin, edhe pse për këtë na është dashur të përdorim pyetësorë të ndërthurur, bashkime, kolona të llogaritura dhe pamje. Po, ndonjëherë duhet të mendosh për të marrë rezultatin, pa të nuk mund të shkosh askund. Por ne prekëm dy tema shumë të rëndësishme - kolonat e llogaritura dhe pamjet. Le të flasim për to në më shumë detaje.

Fushat e llogaritura (kolonat)

Në një shembull, ne kemi shqyrtuar sot një fushë të llogaritur matematikore. Këtu do të doja të shtoja se mund të përdorni jo vetëm operacionin e shumëzimit (*), por edhe zbritjen (-), dhe mbledhjen (+), dhe ndarjen (/). Sintaksa është si më poshtë:

SELECT emri_col_1, emri_col_2, emri_col_1*emri_col_2 SI i llogaritur_emri_kolones FROM_emri i tabeles;

Nuanca e dytë është fjala kyçe AS, e kemi përdorur për të vendosur emrin e kolonës së llogaritur. Në fakt, kjo fjalë kyçe vendos pseudonime për çdo kolonë. Pse është e nevojshme kjo? Për reduktimin dhe lexueshmërinë e kodit. Për shembull, pamja jonë mund të duket si kjo:

KRIJO PAMJE report_vendor SI SELECT A.id_product, A.sasi, B.price, A.sasi*B.price AS përmbledhje NGA revista_incoming AS A, çmimet AS B WHERE A.id_product= B.id_product AND id_incoming= (SELECT id_incoming FROM WHERE id_shitësi=2);

Pajtohuni që kjo është shumë më e shkurtër dhe më e qartë.

Përfaqësimi

Ne kemi konsideruar tashmë sintaksën për krijimin e pamjeve. Pasi të krijohen pamjet, ato mund të përdoren në të njëjtën mënyrë si tabelat. Kjo do të thotë, kryeni pyetje mbi to, filtroni dhe renditni të dhënat, kombinoni një pamje me një tjetër. Nga njëra anë, kjo është një mënyrë shumë e përshtatshme për të ruajtur pyetjet komplekse të përdorura shpesh (si në shembullin tonë).

Por duhet mbajtur mend se pamjet nuk janë tabela, domethënë ato nuk ruajnë të dhëna, por vetëm i marrin ato nga tabelat e tjera. Prandaj, së pari, gjatë ndryshimit të të dhënave në tabela, do të ndryshojnë edhe rezultatet e prezantimit. Dhe së dyti, kur kërkohet një pamje, kërkohen të dhënat e nevojshme, domethënë ulet performanca e DBMS. Prandaj, ato nuk duhet të abuzohen.

Le të mësojmë të përmbledhim. Jo, këto nuk janë rezultatet e mësimit të SQL, por rezultatet e vlerave të kolonave të tabelave të bazës së të dhënave. Funksionet e agregatit SQL funksionojnë në vlerat e një kolone për të prodhuar një vlerë të vetme rezultati. Funksionet agregate SQL më të përdorura janë SUM, MIN, MAX, AVG dhe COUNT. Ekzistojnë dy raste në të cilat duhet të përdoren funksionet agregate. Së pari, funksionet agregate përdoren vetë dhe kthejnë një vlerë të vetme rezultati. Së dyti, funksionet agregate përdoren me klauzolën SQL GROUP BY, domethënë me grupimin sipas fushave (kolonave) për të marrë vlerat që rezultojnë në secilin grup. Konsideroni fillimisht rastet e përdorimit të funksioneve agregate pa grupim.

Funksioni SQL SUM

Funksioni SQL SUM kthen shumën e vlerave të një kolone në një tabelë të bazës së të dhënave. Mund të aplikohet vetëm për kolonat vlerat e të cilave janë numra. Pyetjet SQL për të marrë shumën që rezulton fillojnë kështu:

ZGJIDH SHUMEN (KOLLONËN) ...

Kjo shprehje ndiqet nga FROM (TABLE_NAME), dhe më pas një kusht mund të specifikohet duke përdorur klauzolën WHERE. Për më tepër, DISTINCT mund t'i vendoset parashtesë emrit të një kolone për të treguar se do të merren parasysh vetëm vlerat unike. Si parazgjedhje, të gjitha vlerat merren parasysh (për këtë, ju mund të specifikoni në mënyrë specifike jo DISTINCT, por ALL, por fjala ALL është opsionale).

Nëse dëshironi të ekzekutoni pyetjet e bazës së të dhënave nga ky mësim në MS SQL Server, por kjo DBMS nuk është e instaluar në kompjuterin tuaj, atëherë mund ta instaloni duke përdorur udhëzimet në këtë lidhje .

Së pari, ne do të punojmë me bazën e të dhënave të kompanisë - Company1. Skripti për krijimin e kësaj baze të dhënash, tabelat e saj dhe plotësimin e tabelave me të dhëna është në skedarin në këtë lidhje .

Shembulli 1 Ekziston një bazë të dhënash e kompanisë me të dhëna për departamentet dhe punonjësit e saj. Tabela e Stafit ka gjithashtu një kolonë me të dhënat e pagave të punonjësve. Zgjedhja nga tabela ka formën e mëposhtme (për të zmadhuar foton, klikoni mbi të me butonin e majtë të miut):

Për të marrë shumën e të gjitha pagave, ne përdorim pyetjen e mëposhtme (në MS SQL Server - me prefiksin USE company1;):

SELECT SUM (Paga) NGA Stafi

Ky pyetje do të kthejë vlerën 287664.63.

Dhe tani . Në ushtrime tashmë po fillojmë të ndërlikojmë detyrat, duke i afruar ato me ato që hasen në praktikë.

Funksioni SQL MIN

Funksioni SQL MIN funksionon gjithashtu në kolona, ​​vlerat e të cilave janë numra dhe kthen minimumin e të gjitha vlerave në kolonë. Ky funksion ka një sintaksë të ngjashme me atë të funksionit SUM.

Shembulli 3 Baza e të dhënave dhe tabela janë të njëjta si në shembullin 1.

Kërkohet të zbulohet paga minimale e punonjësve të departamentit numër 42. Për ta bërë këtë, ne shkruajmë pyetjen e mëposhtme (në MS SQL Server - me prefiksin USE company1;):

Kërkesa do të kthejë vlerën 10505.90.

Dhe perseri ushtrim për vetëvendosje. Në këtë dhe disa ushtrime të tjera, do t'ju duhet jo vetëm tabela e Stafit, por edhe tabela Org që përmban të dhëna për divizionet e kompanisë:


Shembulli 4 Tabela Org i shtohet tabelës Staff, që përmban të dhëna për divizionet e kompanisë. Tregoni numrin minimal të viteve që një punonjës i vetëm ka punuar në një departament të vendosur në Boston.

Funksioni SQL MAX

Funksioni SQL MAX funksionon në mënyrë të ngjashme dhe ka një sintaksë të ngjashme, e cila përdoret kur dëshironi të përcaktoni vlerën maksimale midis të gjitha vlerave të një kolone.

Shembulli 5

Kërkohet të zbulohet paga maksimale e punonjësve të departamentit numër 42. Për ta bërë këtë, ne shkruajmë pyetjen e mëposhtme (në MS SQL Server - me prefiksin USE company1;):

Kërkesa do të kthejë vlerën 18352.80

Tani eshte koha ushtrime për vetëvendosje.

Shembulli 6 Përsëri po punojmë me dy tabela - Stafi dhe Org. Shfaq emrin e departamentit dhe shumën maksimale të komisioneve të marra nga një punonjës në departamentin që i përket grupit të departamenteve (Divizioni) Lindor. Përdorni JOIN (bashkimi i tabelave) .

Funksioni SQL AVG

Ajo që u tha për sintaksën për funksionet e përshkruara më parë është gjithashtu e vërtetë për funksionin SQL AVG. Ky funksion kthen mesataren e të gjitha vlerave në një kolonë.

Shembulli 7 Baza e të dhënave dhe tabela janë të njëjta si në shembujt e mëparshëm.

Le të kërkohet të zbuloni kohëzgjatjen mesatare të shërbimit të punonjësve të departamentit numër 42. Për ta bërë këtë, ne shkruajmë pyetjen e mëposhtme (në MS SQL Server - me prefiksin USE company1;):

Rezultati do të jetë 6.33

Shembulli 8 Ne punojmë me një tavolinë - Stafi. Tregoni pagën mesatare të punonjësve me përvojë nga 4 deri në 6 vjet.

Funksioni SQL COUNT

Funksioni SQL COUNT kthen numrin e regjistrimeve në një tabelë të bazës së të dhënave. Nëse specifikoni SELECT COUNT(COLUMNAME) ... në pyetje, atëherë rezultati do të jetë numri i regjistrimeve pa marrë parasysh ato rekorde në të cilat vlera e kolonës është NULL (e papërcaktuar). Nëse përdorni një yll si argument dhe filloni një pyetje SELECT COUNT(*) ..., rezultati do të jetë numri i të gjitha rekordeve (rreshtave) në tabelë.

Shembulli 9 Baza e të dhënave dhe tabela janë të njëjta si në shembujt e mëparshëm.

Ju dëshironi të dini numrin e të gjithë punonjësve që marrin komisione. Numri i punonjësve, vlerat e kolonës Comm të të cilëve nuk janë NULL, do të kthejë pyetjen e mëposhtme (në MS SQL Server - me kompaninë USE1; konstruksioni i mëparshëm):

ZGJIDH NUMRIN (Kom) NGA Stafi

Rezultati do të jetë vlera 11.

Shembulli 10 Baza e të dhënave dhe tabela janë të njëjta si në shembujt e mëparshëm.

Nëse duhet të zbuloni numrin e përgjithshëm të regjistrimeve në tabelë, atëherë përdorni pyetjen me një yll si argument për funksionin COUNT (në MS SQL Server - me prefiksin USE company1;):

ZGJIDH NUMRIN (*) NGA Stafi

Rezultati do të jetë vlera 17.

Tjetra ushtrim për vetëvendosje ju duhet të përdorni një nënpyetje.

Shembulli 11. Ne punojmë me një tavolinë - Stafi. Shfaq numrin e punonjësve në departamentin e Plains.

Funksionet Agregate me SQL GROUP BY

Tani le të shohim përdorimin e funksioneve agregate së bashku me klauzolën SQL GROUP BY. Klauzola SQL GROUP BY përdoret për të grupuar vlerat që rezultojnë sipas kolonave në një tabelë të bazës së të dhënave. Faqja ka mësim kushtuar këtij operatori veç e veç .

Ne do të punojmë me bazën e të dhënave "Portali i Njoftimeve 1". Skripti për krijimin e kësaj baze të dhënash, tabelën e saj dhe plotësimin e tabelës së të dhënave është në skedarin në këtë lidhje .

Shembulli 12. Pra, ekziston një bazë të dhënash e portalit të reklamave. Ka një tabelë reklamash që përmban të dhëna për reklamat që janë dorëzuar për javën. Kolona Kategoria përmban të dhëna për kategoritë e mëdha të reklamave (për shembull, Pasuri të paluajtshme) dhe kolona Pjesë përmban të dhëna për pjesët më të vogla që përfshihen në kategori (për shembull, pjesët e apartamenteve dhe vilave janë pjesë e kategorisë së pasurive të paluajtshme). Kolona Njësitë përmban të dhëna për numrin e reklamave të dorëzuara dhe kolona Paratë përmban shumën e parave të fituara për paraqitjen e reklamave.

KategoriapjesëNjësitëParatë
Transportimjetet motorike110 17600
Pasuri të paluajtshmeApartamente89 18690
Pasuri të paluajtshmeDachas57 11970
TransportiMotoçikleta131 20960
Materiale ndërtimidërrasat68 7140
inxhinieri elektrikeTV127 8255
inxhinieri elektrikeFrigoriferë137 8905
Materiale ndërtimiRegjistrat112 11760
Koha e lirëlibra96 6240
Pasuri të paluajtshmeShtëpitë47 9870
Koha e lirëMuzikë117 7605
Koha e lirëLojëra41 2665

Duke përdorur klauzolën SQL GROUP BY, gjeni shumën e parave të krijuara duke paraqitur reklama në secilën kategori. Ne shkruajmë pyetjen e mëposhtme (në MS SQL Server - me prefiksin USE adportal1;):

ZGJIDH Kategorinë, SHUMA (Paratë) SI PARA NGA REKLAMAT GRUP SIPAS Kategorisë

Shembulli 13 Baza e të dhënave dhe tabela janë të njëjta si në shembullin e mëparshëm.

Duke përdorur klauzolën SQL GROUP BY, zbuloni se cila pjesë e secilës kategori kishte më shumë reklama. Ne shkruajmë pyetjen e mëposhtme (në MS SQL Server - me prefiksin USE adportal1;):

ZGJIDH Kategorinë, Pjesë, MAX (njësi) AS Maksimumi NGA REKLAMAT GRUPI SIPAS Kategorisë

Rezultati do të jetë tabela e mëposhtme:

Vlerat totale dhe individuale mund të merren në një tabelë duke kombinuar rezultatet e pyetjeve duke përdorur operatorin UNION .

Bazat e të dhënave relacionale dhe gjuha SQL



Artikuj të ngjashëm: