SQL - 3. del

SQL - 3. del

Avtor: Matija Lokar

SELECT

  • Povpraševanje po podatkih
  • Vrne tabelo
  • Osnovna struktura

    • SELECT seznam podatkov, ki jih želimo videti
      FROM seznam tabel, kjer bomo podatke našli
      WHERE pogoji, ki določajo, katere podatke želimo videti
  • Dodatki

    • AS : pre(po)imenujemo izhodni stolpec
    • ORDER BY : uredimo vrstice
    • DISTINCT : v končnem rezultatu upoštevamo le različne vrstice

SELECT - primer

  • select name, round(population/1000000)
         AS  prebiMilion FROM bbc WHERE region
         IN ('Asia', 'Europe')AND name LIKE 'C%'
  • Razčlenimo

    • Izpiši ime in število prebivalcev v milionih.
    • Drugi stolpec poimenuj prebiMilion
    • Podatke pridobi iz tabele bbc
    • Upoštevaj tiste vrstice, kjer je vrednost stolpca region bodisi 'Asia' bodisi 'Europe' in kjer se vrednost v stolpcu ime začne s črko C
  • Pomen

    • Izpiši imena in število prebivalcev tistih evropskih in azijskih držav, katerih imena se začno s C
(tabela2.jpg)

Poizvedbe s podpoizvedbami

  • Kot določeno vrednost v izrazih lahko uporabimo tudi rezultate ukaza SELECT
  • SELECT name FROM bbc
         WHERE region = 'Europe' AND population <=
             (SELECT population FROM bbc
                    WHERE name='Slovenia')

    • Izpiši imena držav, ki imajo manj prebivalcev kot Slovenija
  • Zakaj?

    • Izločimo vrstice, kjer regija ni 'Europe'
    • Izračunamo tabelo s stolpcem population kjer upoštevamo le tiste vrstice, kjer je ime države 'Slovenia'
    • Ker ima ta tabela le eno vrstico, lahko zahtevamo, da iz tabele, kjer smo odstranili vrstice, kjer regija ni Evropa, upoštevamo le tiste, kjer je vrednost v population večja od te, pravkar naračunane vrednosti
  • Podpoizvedbe naj bi vračale le en stolpec z eno vrednostjo! Drugače pride do napake

    • Stolpec ima lahko več vrednosti le, če rezultat poizvedbe uporabimo, kjer imamo lahko več vrednosti (seznam)

      • Operator IN

        • IN (SELECT ... )
      • Zanima nas, če je vrednost ena izmed vrednosti v stolpcu

Poizvedbe s podpoizvedbami - primer

  • Tabela: nobel(yr, subject, winner)
  • Izpiši leta, kjer je bila podeljena Nobelova nagrada za fiziko in ne za kemijo
  • Kako:

    • Upoštevamo stolpce, kjer je subject ='physics'
    • Izločimo vrstice, kjer je vrednost v stolpcu yr ena od tistih vrednosti, ki nastopajo v stolpcu yr pri tistih vrsticah, kjer je subject = 'chemistry' )
  • SELECT distinct yr FROM nobel
         WHERE subject = 'physics'
              AND yr NOT IN (SELECT yr FROM nobel WHERE subject = 'chemistry')
  • Zakaj distinct?

    • Lahko je več dobitnikov za fiziko v istem letu!

Združevalne funkcije

  • AVG, MAX, MIN, SUM, COUNT

    • Vse upoštevajo neničelne vrednosti!
    • SELECT * FROM bbc
            WHERE region = 'Asia'
                 AND    name < 'C' AND name <> 'Bangladesh'
(tabela3.jpg)

SELECT AVG(gdp) FROM bbc
      WHERE region = 'Asia'
         AND    name < 'C' AND name <> 'Bangladesh'

(tabela4.jpg)

Združevalne funkcije

  • COUNT (stolpec) : število vrstic z neničelno vrednostjo v stolpcu

    • SELECT COUNT(gdp) FROM bbc
    • Število držav, kjer je poznan BDP (podatek je v tabeli)
  • COUNT (DISTINCT stolpec) : število različnih vrednosti

    • SELECT COUNT(DISTINCT region) FROM bbc
    • Število regij, ki so v tabeli držav

Združevalne funkcije in težave

  • Denimo, da nas zanima ime afriške države z največ prebivalci

    • SELECT name, MAX(population) FROM bbc
            WHERE region="Africa
      "
    • sql: Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no
      GROUP columns is illegal if there is no GROUP BY clause
    • Zakaj?

      • Če malo pomislimo, je tole čista neumnost
      • Dejansko s tem hočemo izpisati imena vseh afriških držav, zraven vsake pa še maksimalno število prebivalcev, ki jo ima država v Afriki

Združevalne funkcije in težave

  • SELECT name, population FROM bbc
         WHERE region="Africa"
            AND population = MAX(population)

    • sql: Invalid use of group function
  • Združevalne funkcije lahko uporabljamo v prvem delu stavka SELECT . Izračunajo neko vrednost prek več vrstic tabele.
  • Rešitev:

    • Subselect
    • SELECT name, population FROM bbc
            WHERE region="Africa"
                AND population =  (SELECT MAX(population) FROM bbc
                                       WHERE    region="Africa")

Združevalne funkcije in skupine podatkov

  • Denimo, da nas zanima maksimalno število prebivalcev države v vsaki regiji

    • SELECT MAX(population) FROM bbc WHERE region = "Europe "
    • SELECT MAX(population) FROM bbc WHERE region = "Asia "
    • ...
    • Moramo poznati vse regije!
    • Cel kup tipkanja
  • GROUP BY

    • Združi podatke glede na vsebino
    • Torej združevalno funkcijo uporabi na vsaki skupini
  • SELECT MAX(population) FROM bbc GROUP BY region

    • Malo neinformativno ;-)
  • SELECT region, MAX(population) FROM bbc GROUP BY region

Skupine

  • Vrstice v tabeli lahko razdelimo v skupine
  • GROUP BY

    (tabela5.jpg) (tabela6.jpg) (tabela7.jpg)
  • SELECT ... FROM tabela ... GROUP BY ...

    • SELECT ime, prispevek FROM donacije GROUP BY ime
    • SELECT ime, prispevek FROM donacije GROUP BY prispevek / 100

Skupine

  • SELECT ... FROM tabela ... GROUP BY ...

    • SELECT ime, prispevek FROM donacije GROUP BY ime
    • SELECT ime, prispevek FROM donacije GROUP BY prispevek / 100
  • Oba stavka sta NAROBE
  • GROUP BY vedno vrne le eno vrstico za posamezno tabelo
  • Standard načeloma zahteva, da moramo pri določanju stolpcev izhodne tabele obvezno uporabiti združevalno funkcijo ali/in pa vrednost po kateri grupiramo in nič drugega!
  • Kaj se zgodi pri zgornjih stavkih

    • Odvisno od RDMBS

GROUP BY

  • SELECT * FROM bbc GROUP BY region
  • MySQL 5

    • Vrne po eno vrstico (državo) za vsako regijo
  • PostgreSQL

    • sql: errorERROR: column "bbc.name" must appear in the
      GROUP BY clause or be used in an aggregate function
  • Oracle

    • sql: ORA-00979: not a GROUP BY expression (DBD ERROR: error possiblynear
      <*> indicator at char 7 in 'SELECT <*>* FROM bbc GROUP BY region ')
  • ...

GROUP BY in WHERE

  • Po posameznih regijah preštej tiste države, kjer je število prebivalcev več kot 200 000 000

    • Mimogrede: so 4 (Kitajska, Indija, ZDA in Indonezija)
    • SELECT region, COUNT(*) AS KolikoDrzav  FROM bbc
            WHERE population > 200000000 GROUP BY region
  • WHERE deluje pred združevanjem. Zato smo najprej dobili tabelo s 4 vrsticami. Te smo potem z Group by razdelili v podtabele po regijah (2: S. Amerika in Azija), COUNT pa je potem preštel število vrstic v posamezni podtabeli
(tabela8.jpg)

GROUP BY in HAVING

  • Kaj pa tole:
  • Izpiši tiste regije, kjer živi vsaj 100 milijonov prebivalcev:
  • Kako uporabiti rezultate združevalnih funkcij v pogojih
  • SELECT region FROM bbc
         WHERE sum(population) >= 100000000
             GROUP BY region
  • Ne gre!
  • Zakaj – WHERE deluje še pred GROUP BY!
(tabela9.jpg)

GROUP BY in HAVING

  • SELECT region FROM bbc
         GROUP BY region  HAVING sum(population) >= 100000000
  • HAVING preverjamo po grupiranju
  • Zato:

    • Najprej smo tabelo razdelili na podtabele po regijah
    • sum(population) je potem seštela prebivalstvo v okviru posamezne regije in upoštevale so le podtabele, ki so izpolnjevale pogoj

Še en zgled

  • nobel(yr, subject, winner)
  • Izpiši tista leta po letu 1970, ko je Nobelovo nagrado iz fizike (Physics) dobil le en posameznik
  • SELECT yr  FROM nobel
         WHERE subject = 'Physics'
              AND yr > 1970
                 GROUP BY yr   HAVING COUNT(yr) = 1
0%
0%