Monimutkaisten SQL-kyselyjen suorittaminen. Tietojoukkojen operaattori PAITSI Sql:n yleiset säännöt lukuun ottamatta esimerkkejä

Kun törmäät usein mihin tahansa tekniikkaan, ohjelmointikieleen tai standardiin, muodostuu tietty kuva niiden kyvyistä ja rajoista, joissa niitä käytetään. Tätä voi jatkua melko pitkään, kunnes silmä tarttuu esimerkkeihin, jotka laajentavat kovettunutta tiedon horisonttia. Tänään haluaisin puhua tällaisista esimerkeistä ja osoittaa ne SQL-kielelle. Mielenkiintoiset ja harvinaiset mallit, unohdetut ilmaisut, omituiset tekniikat odottavat sinua tässä artikkelissa. Kaikki kiinnostuneet tervetuloa kissoihin.

Vivahteita

Minulta kysytään usein, kenelle tämä artikkeli on tarkoitettu? Mutta uskokaa minua, vastauksen antaminen ei ole aina helppoa: toisaalta on ninjakehittäjiä, joita on vaikea yllättää millään, ja toisaalta nuoria padawaneja. Mutta yhden asian voin sanoa varmaksi - SQL:stä kiinnostuneelle lukijalle, joka pystyy täydentämään rikasta kuvaansa pienillä, mutta erittäin mielenkiintoisilla yksityiskohdilla. Tämä artikkeli ei sisällä kilometrien pituisia sivuja sql-kyselyitä, enintään 1 tai 2 riviä ja vain sitä, mikä on mielestäni harvinaista. Mutta koska haluan olla täysin rehellinen, jos et ole vieras sql, artikkeli näyttää hieman tylsältä. Kaikki artikkelin esimerkit ensimmäistä ja neljättä lukuun ottamatta voidaan katsoa SQL-92-standardin ansioksi.

Data

Elämämme helpottamiseksi olen asettanut yksinkertaisen tietokilven, jossa tiettyjä kohtia testataan ja lyhyyden vuoksi annan niistä kokeen tuloksen. Tarkistan kaikki kyselyt PostgreSql:stä.

Skriptit ja datataulukko

CREATE TABLE tavarat(id bigint NOT NULL, nimimerkki vaihtuva(127) NOT NULL, kuvausmerkki vaihteleva(255) NOT NULL, hinta numeerinen(16,2) NOT NULL, articul merkki vaihteleva(20) NOT NULL, act_time aikaleima NOT NULL , saatavuus boolean NOT NULL, CONSTRAINT pk_goods PRIMARY KEY (id)); LISÄÄ tavaroihin (tunnus, nimi, kuvaus, hinta, articul, act_time, saatavuus) ARVOT (1, "tossut", "pehmeä", 100.00, "TR-75", (ts "2017-01-01 01:01: 01.01"), TOSI); INSERT INTO tavaroihin (tunnus, nimi, kuvaus, hinta, articul, act_time, saatavuus) ARVOT (2, "Tyyny", "Valkoinen", 200.00, "PR-75", (ts "2017-01-02 02:02: 02.02"), TOSI); LISÄÄ tavaroihin (tunnus, nimi, kuvaus, hinta, articul, act_time, saatavuus) ARVOT (3, "Blanket", "Down", 300.00, "ZR-75", (ts "2017-01-03 03:03: 03.03"), TOSI); LISÄÄ tavaroihin (tunnus, nimi, kuvaus, hinta, articul, act_time, saatavuus) ARVOT (4, "Tyynyliina", "Harmaa", 400.00, "AR-75", (ts "2017-01-04 04:04: 04.04"), EPÄTOSI); INSERT INTO tavaroihin (tunnus, nimi, kuvaus, hinta, articul, act_time, saatavuus) ARVOT (5, "Sheet", "Silk", 500.00, "BR-75", (ts "2017-01-05 05:05: 05.05"), EPÄTOSI);

Pyynnöt

1. Lainausmerkit

Ja ensimmäinen asia, joka minulla on, on yksinkertainen kysymys: Voitko antaa esimerkin sql-kyselystä käyttämällä kaksinkertainen lainausmerkit? Kyllä, ei sinkkujen, nelinpelien kanssa?

Esimerkki lainausmerkeillä

VALITSE nimi "Tuotteen nimi" tuotteista


Olin hyvin yllättynyt, kun näin tämän ensimmäistä kertaa. Jos yrität muuttaa lainausmerkit yksittäisiksi lainausmerkeiksi, tulos on täydellinen muu!

Tämä ei ehkä vaikuta kovin hyödylliseltä esimerkiltä todellisen kehityksen kannalta. Minulle tämä ei pidä paikkaansa. Nyt käytän sitä aktiivisesti kaikissa SQL-malleissani. Asia on yksinkertainen: kun palaat puolen vuoden kuluttua 40 sarakkeen sql-kyselyyn, oi kuinka heidän "meidän" nimensä pelastaa sinut. Huolimatta siitä, etten kertonut SQL-92:sta, sisään uusin painos Siinä mainitaan kaksoislainausmerkit.

2. Pseudopöytä. SQL-92

Se on terminologian kannalta hieman epätarkka, mutta ydin on yksinkertainen - FROM-osion alikyselystä johtuva taulukko. Ehkä eniten tunnettu tosiasia Tässä artikkelissa

Pseudopöytä

SELECT mock.nickname "Lempinimi", (CASE WHEN mock.huff THEN "Yes" MUUTA "Ei" END) "Loukuttu?" FROM (VALITSE nimi AS lempinimi, saatavuus AS huff FROM tavarat) pila

Esimerkissämme mock on pseudotaulukko (jota joskus kutsutaan virtuaalitaulukoksi). Luonnollisesti niiden tarkoituksena ei ole lainkaan vääristää todellista merkitystä. Esimerkki on tämä.

3. Tietolohkokonstruktori. SQL-92

Se kuulostaa pelottavalta, koska en ole löytänyt hyvää käännöstä tai tulkintaa. Ja kuten aina, se on helpompi selittää esimerkillä:

Esimerkki tietolohkon rakentajasta

VALITSE nimi "Tuotteen nimi", hinta "Hinta" FROM (ARVOT ("Tohvelit", 100,00), ("Tyyny", 200,00)) AS tavarat(nimi, hinta)

Tuotteen nimi Hinta
Tossut 100.00
Tyyny 200.00

Osassa FROM käytetty avainsana ARVOT, jonka jälkeen tiedot suluissa, rivi riviltä. Asia on siinä, että emme valitse tietoja mistään taulukosta, vaan luomme sen lennossa, "kutsumme" sitä taulukoksi, nimeämme sarakkeet ja käytämme sitä sitten oman harkintamme mukaan. Tämä asia osoittautui erittäin hyödylliseksi testattaessa erilaisia ​​sql-kyselytapauksia, kun joistakin taulukoista ei ole tietoja (paikallisessa tietokannassasi) ja lisäyksen kirjoittaminen on liian laiska tai joskus erittäin vaikeaa taulukoiden ja rajoitusten vuoksi. .

4. Aika, päivämäärä ja aika ja päivämäärä

Todennäköisesti jokainen on kohdannut pyynnöissä tarpeen määrittää aika, päivämäärä tai päivämäärä ja kellonaika. Monet DBMS:t tukevat literaaleja t, d ja ts, vastaavasti, näiden tyyppien kanssa työskentelyä varten. Mutta se on helpompi selittää esimerkillä: Literaaleille d ja t kaikki on samanlaista.
Pyydän lukijalta anteeksi, että johdin harhaan, mutta kaikki kohdassa 4 sanottu ei liity SQL-kieleen, vaan liittyy JDBC:n kyselyiden esikäsittelyn ominaisuuksiin.

5. Kieltäminen. SQL-92

Me kaikki tiedämme operaattorista EI, mutta hyvin usein he unohtavat, että sitä voidaan soveltaa sekä predikaattiryhmään että yhteen sarakkeeseen:

6. Tietolohkojen vertailu. SQL-92

Pyydän vielä kerran anteeksi terminologiaa. Tämä on yksi suosikkiesimerkeistäni

Esimerkki tietolohkojen vertailusta

SELECT * FROM products WHERE (nimi, hinta, saatavuus) = ("Tyynyliina", 400,00, FALSE) -- tai sitä vastaava SELECT * FROM products WHERE nimi = "Tyynyliina" JA hinta = 400,00 JA saatavuus = EPÄTOSI

Kuten esimerkistä voidaan nähdä, tietolohkojen vertailu on samanlaista kuin elementtikohtainen vertailu merkitys_ 1 _block_1 = arvo_ 1 _lohko_2, arvo_ 2 _block_1 = arvo_ 2 _lohko_2, arvo_ 3 _block_1 = arvo_ 3 _block_2 käyttämällä JA heidän välillään.

7. Vertaile operaattoreita muuntimilla ANY, SOME tai ALL. SQL-92

Tässä tarvitaan selvennystä. Mutta kuten aina, ensin esimerkki Mitä se tarkoittaa KAIKKI tässä tapauksessa? Ja se tarkoittaa, että valintaehto täyttyy vain niillä rivillä, joiden tunnisteet (tapauksessamme nämä ovat 4 ja 5) ovat suuremmat minkä tahansa alikyselyssä löydetyistä arvoista (1, 2 ja 3). 4 on suurempi kuin 1 ja kuin 2 ja kuin 3. 5 on sama. Mitä tapahtuu, jos vaihdamme KAIKKI päällä MINKÄ TAHANSA?
Mitä se tarkoittaa MINKÄ TAHANSA tässä tapauksessa? Ja se tarkoittaa, että valintaehdon täyttyvät vain ne rivit, joiden tunnisteet (tapauksessamme nämä ovat 2, 3, 4 ja 5) ovat suuremmat ainakin yksi alikyselyssä löydetyistä arvoista (1, 2 ja 3). Itselleni liityin KAIKKI Kanssa JA, A MINKÄ TAHANSA Kanssa TAI. JONKIN VERRAN Ja MINKÄ TAHANSA analogeja toisilleen.

8. Operaattorit työskentelyyn pyyntöjen kanssa. SQL-92

On tunnettua, että voit yhdistää 2 kyselyä keskenään käyttämällä operaattoreita LIITTO tai UNIONI KAIKKI. Tätä käytetään usein. Mutta on vielä 2 operaattoria PAITSI Ja RISTEKSI.

Esimerkki: EXCEPT

Itse asiassa toisen joukon tiedot jätetään pois ensimmäisestä arvojoukosta.
Itse asiassa ensimmäisen arvojoukon ja toisen joukon leikkaus tapahtuu.
Siinä kaikki, kiitos huomiosta.

Pääkirjoitus

N1. Kiitos streetflushille rakentavasta kritiikistä. Kirjoitti artikkelin, joka sisältää tietoa siitä, mikä on kielistandardi ja mikä ei.
N2. Kohta 4 on korjattu selventämään, että ts/d/t ei ole osa SQL-kieltä. Kiitos huomiostasi Melkij.

INTERSECT-operaattori hakee identtiset rivit yhden tai useamman kyselyn tulosjoukoista. Joissakin suhteissa INTERSECT-operaattori on hyvin samanlainen kuin INNER JOIN.

INTERSECT kuuluu tietojoukkojen käsittelyyn tarkoitettujen operaattorien luokkaan (joukkooperaattori). Muita tällaisia ​​operaattoreita ovat EXCEPT ja UNION. Kaikkia joukkooperaattoreita käytetään kahden tai useamman kyselyn tulosjoukkojen käsittelemiseen samanaikaisesti, mistä johtuu niiden nimi.

SQL2003 syntaksi

INTERSECT-operaattorin kyselyiden määrälle ei ole teknisiä rajoituksia. Yleinen syntaksi Seuraava.

RISTEKSI

] RISTIKKO

Avainsanat

Päällekkäiset rivit kaikista tulosjoukoista sisältyvät.

ERITTÄVÄ

Päällekkäiset rivit poistetaan kaikista tulosjoukoista ennen kuin INTERSECT-operaattori suorittaa vertailun. Sarakkeet, joissa on tyhjät (NULL) arvot, katsotaan kaksoiskappaleiksi. Jos avainsanaa ALL tai DISTINCT ei ole määritetty, oletuksena on DISTINCT.

VASTAAVA

Määrittää, että vain sarakkeet, joilla on sama nimi molemmissa kyselyissä, palautetaan, vaikka jokerimerkkiä (*) käytettäisiin molemmissa kyselyissä.

Määrittää, että vain nimetyt sarakkeet palautetaan, vaikka kyselyt kohtaisivat muita sarakkeita, joilla on vastaavat nimet. Tätä lausetta tulee käyttää yhdessä avainsanan CORESPONDING kanssa.

Yleiset säännöt

On vain yksi tärkeä sääntö muistaa työskennellessäsi INTERSECT-operaattorin kanssa.

Sarakkeiden järjestyksen ja lukumäärän on oltava sama kaikissa kyselyissä. Myös vastaavien sarakkeiden tietotyyppien on oltava yhteensopivia.

Esimerkiksi tyypit CHAR ja VARCHAR ovat yhteensopivia. Oletusarvoisesti tulosjoukko kussakin sarakkeessa on koko, joka vastaa suurinta tyyppiä kussakin tietyssä paikassa.

Kumpikaan alusta ei tue VASTAAVAA lauseketta.

ANSI-standardin mukaan INTERSECT-operaattorilla on korkeampi prioriteetti kuin muilla joukkooperaattoreilla, vaikka tällaisten operaattorien etusija käsitellään eri alustoilla eri tavalla. Voit ohjata operaattorin ensisijaisuutta suluilla. Muussa tapauksessa DBMS voi suorittaa ne järjestyksessä vasemmalta oikealle tai ensimmäisestä viimeiseen.

ANSI-standardin mukaan kyselyssä voi käyttää vain yhtä ORDER BY -lausetta. Lisää se aivan viimeisen SELECT-käskyn loppuun. Jotta sarakkeiden ja taulukoiden nimeämisessä ei olisi epäselvyyttä, muista määrittää sama alias kaikille vastaaville taulukon sarakkeille. Esimerkiksi:

Alustalla, joka ei tue INTERSECT-operaattoria, voit korvata sen FULL JOIN -alikyselyllä.

SELECT a.au_lname AS "sukunimi", a.au_fname AS "etunimi" tekijöiltä INTERSECT:nä SELECT e.emp_lname AS "sukunimi", e.emp_fname AS "etunimi" työntekijöiltä AS e ORDER BY sukunimi, etunimi;

Koska eri INTERSECT-käskyjen sarakkeiden tietotyypit voivat olla yhteensopivia, eri RDBMS-alustoilla voi olla erilaisia ​​vaihtoehtoja eripituisten sarakkeiden käsittelyyn. Esimerkiksi, jos edellisen esimerkin ensimmäisen kyselyn aujname-sarake on huomattavasti pidempi kuin toisen kyselyn empjname-sarake, eri alustoilla voi olla erilaiset säännöt lopullisen tuloksen pituuden määrittämiseksi. Mutta yleisesti ottaen alustat valitsevat pidemmän (ja vähemmän rajoittavan) koon tulokselle.

Jokaisella RDBMS:llä voi olla omat sääntönsä sarakkeen nimen käytölle, jos sarakeluetteloiden nimet ovat erilaisia. Tyypillisesti käytetään ensimmäisen kyselyn sarakkeiden nimiä.

DB2

DB2-alusta tukee ANSI-avainsanoja INTERSECT ja INTERSECT ALL sekä valinnaista VALUES-lausetta.

(käsky._SELECT_7 | ARVOT (laus7 [, ...])) LIIKE

] (käsky_SCJ_2 | ARVOT (laus2 [, ...])) INTERSECT

Vaikka INTERSECT DISTINCT -lausetta ei tueta, toiminnallinen vastine on INTERSECT. CORESPONDING-lausetta ei tueta.

Lisäksi tietotyypit LONG VARCHAR, LONG VARGRAPHIC, BLOB, CLOB, DBCLOB, DATALINK ja rakenteelliset tyypit ei käytetä INTERSECT-lauseessa, mutta niitä voidaan käyttää INTERSECT ALL -lauseessa.

Jos tulosjoukossa on sarake, jolla on sama nimi kaikissa SELECT-käskyissä, sitä nimeä käytetään käskyn palauttaman sarakkeen lopullisena nimenä. Jos kyselyissä kuitenkin käytetään eri nimiä sarakkeelle, DB2 luo uuden nimen tuloksena olevalle sarakkeelle. Tämän jälkeen siitä tulee käyttökelvoton ORDER BY- ja FOR UPDATE -lausekkeissa.

Jos yksittäinen kysely käyttää useita operaattoreita tietojoukkojen käsittelyyn, suluissa oleva kysely suoritetaan ensin. Tämän jälkeen suoritusjärjestys on vasemmalta oikealle. Kaikki INTERSECT-käskyt suoritetaan kuitenkin ennen UNION- ja EXCEPT-lauseita, esimerkiksi:

SELECT empno FROM työntekijä WHERE työosasto LIKE "E%" RISTEKSI (VALITSE empno FROM emp_act WHERE projno IN ("IF1000", "IF2000", "AD3110") UNIONIN ARVOT ("AA0001"), ("AB0002"), ("AC003" "))

Yllä oleva esimerkki hakee kaikkien E-kirjaimella alkavalla osastolla työskentelevien työntekijöiden tunnukset työntekijätaulukosta. Tunnukset haetaan kuitenkin vain, jos ne ovat myös työntekijätilitaulukossa nimeltä emp_act ja osallistuvat projekteihin IF1000, IF200 ja AD3110.

On vain yksi tärkeä sääntö, joka on muistettava käytettäessä EXCEPT-lausetta.

Sarakkeiden järjestyksen, lukumäärän ja tietotyyppien on oltava samat kaikissa kyselyissä.

ANSI-standardin mukaan joukkooperaattoreilla UNION ja EXCEPT on sama etusija, mutta INTERSECT-operaattori suoritetaan ennen muita joukkooperaattoreita. Suosittelemme ohjaamaan operaattorin etusijaa suluilla. Tämä on yleensä erittäin hyvä käytäntö.

ANSI-standardin mukaan kyselyssä voi käyttää vain yhtä ORDER BY -lausetta. Lisää se aivan viimeisen SELECT-käskyn loppuun. Jotta sarakkeiden ja taulukoiden nimeämisessä ei olisi epäselvyyttä, muista määrittää sama alias kaikille vastaaville taulukon sarakkeille. Esimerkiksi:

SELECT au_lname AS "sukunimi", au_fname AS "etunimi" tekijöiltä EXCEPT SELECT emp_lname AS "sukunimi", emp_fname AS "etunimi" työntekijöiltä ORDER BY sukunimi, etunimi;

Lisäksi, koska jokainen sarakeluettelo voi määrittää sarakkeita, joissa on vastaavasti yhteensopivia tietotyyppejä, eri RDBMS-alustoilla voi olla erilaisia ​​vaihtoehtoja eripituisten sarakkeiden käsittelyyn. Esimerkiksi, jos edellisen esimerkin ensimmäisen kyselyn sarake au_lname on huomattavasti pidempi kuin toisen kyselyn sarake emp_lname, eri alustoilla voi olla erilaiset säännöt lopullisen tuloksen pituuden määrittämiseksi. Mutta yleisesti ottaen alustat valitsevat pidemmän (ja vähemmän rajoittavan) koon tulokselle.

Jokaisella RDBMS:llä voi olla omat sääntönsä sarakkeen nimen käytölle, jos sarakeluetteloiden nimet ovat erilaisia. Yleensä käytetään ensimmäisen kyselyn sarakkeiden nimiä.

Tietotyyppien ei tarvitse olla identtisiä, mutta niiden on oltava yhteensopivia. Esimerkiksi tyypit CHAR ja VARCHAR ovat yhteensopivia. Oletusarvoisesti tulosjoukko kussakin sarakkeessa on koko, joka vastaa suurinta tyyppiä kussakin tietyssä paikassa. Esimerkiksi kyselyssä, joka hakee tietoja sarakkeista, jotka sisältävät tyypin VARCHAR(IO) ja VARCHAR(15) arvoja, käytetään VARCHAR(15) -tyyppiä ja -kokoa.

Kumpikaan alusta ei tue VASTAAVAA )) PAITSI lauseketta

(VALITSE lauseke.2 | ARVOT (lausekel, lauseke2 [, ...])) EXCEPT

Voit määrittää yhden tai useamman manuaalisesti määritetyn sarakkeen, joka sisältyy lopputulosjoukkoon. (Tätä kutsutaan rivikonstruktoriksi.) VALUES-lauseen on määritettävä täsmälleen niin monta saraketta kuin EXCEPT-lausekyselyissä. Vaikka EXCEPT DISTINCT -käskyä ei tueta, toiminnallinen vastine on EXCEPT. CORESPONDING-lausetta ei tueta. Lisäksi tietotyyppejä LONG VARCHAR, LONG VARGRAPHIC, BLOB, CLOB, DBCLOB, DATALINK ja rakennetyyppejä ei käytetä EXCEPT-lauseessa, mutta niitä voidaan käyttää EXCEPT ALL -lauseessa.

Jos tulosjoukossa on sarake, jolla on sama nimi kaikissa SELECT-käskyissä, sitä nimeä käytetään käskyn palauttaman sarakkeen lopullisena nimenä. Jos tiettyä saraketta kutsutaan eri tavalla erilaisia ​​ohjeita SELECT, sinun on nimettävä sarake uudelleen kaikissa kyselyissä käyttämällä kaikissa kyselyissä samaa AS-aliaslausetta.

Jos yksittäinen kysely käyttää useita operaattoreita tietojoukkojen käsittelyyn, suluissa oleva kysely suoritetaan ensin. Tämän jälkeen suoritusjärjestys on vasemmalta oikealle. Kaikki INTERSECT-käskyt suoritetaan kuitenkin ennen UNION- ja EXCEPT-lauseita. Esimerkiksi:

SELECT empno FROM työntekijä WHERE työosasto LIKE "E%" EXCEPT SELECT empno FROM emp_act WHERE projno IN (TF1000", TF2000", -AD3110")) UNIONIN ARVOT ("AA0001"), ("AB0002"), ("AC003" ;

Yllä olevassa esimerkissä kaikkien E-kirjaimella alkavalla osastolla työskentelevien työntekijöiden tunnukset haetaan työntekijätaulukosta, minkä jälkeen projekteissa IF1000, IF200 ja AD3110 työskentelevien tunnukset poistetaan työntekijätilitaulukosta (emp_act Lopuksi lisätään kolme lisätunnusta - AA0001, AB0002 ja AC0003 UNION set -operaattorilla.

MySQL

MySQL ei tue EXCEPT-operaattoria. Vaihtoehtoisesti voit käyttää NOT IN tai NOT EXISTS -operaattoreita.

SQL tarjoaa kaksi tapaa yhdistää taulukoita:
  • määritetään yhdistettävät taulukot (mukaan lukien alikyselyt) SELECT-käskyn FROM-lauseessa. Ensin taulukot yhdistetään, ja vasta sitten WHERE-lauseen määrittelemiä ehtoja sovelletaan tuloksena olevaan joukkoon, GROUP BY -lauseen määrittelemään aggregaatioon, tietojen järjestykseen jne.;
  • määritellään SELECT-käskyn käsittelyllä saatujen tulosjoukkojen liitto. Tässä tapauksessa kaksi SELECT-lausetta yhdistetään lauseella LIITTO, RISTEKSI, PAITSI tai VASTAAVAT.

LIITTO

Lause LIITTO yhdistää kahden kyselyn tulokset seuraavien sääntöjen mukaisesti:

Standardi ei aseta rajoituksia tulosjoukon rivien järjestykselle. Näin ollen jotkut DBMS:t näyttävät ensin ensimmäisen kyselyn tuloksen ja sitten toisen kyselyn tuloksen. Oracle DBMS lajittelee tietueet automaattisesti ensimmäisen määritetyn sarakkeen mukaan, vaikka sille ei olisi luotu indeksiä.

Voit määrittää vaaditun lajittelujärjestyksen tarkasti käyttämällä ORDER BY -lausetta. Tässä tapauksessa voit käyttää sekä sarakkeen nimeä että sen numeroa (kuva 4.3).


Riisi. 4.3.

Lause LIITTO ALL suorittaa kahden alikyselyn yhdistämisen, joka on samanlainen kuin UNION-lause seuraavin poikkeuksin:

  • vastaavia rivejä ei poisteta luodusta tulosjoukosta;
  • yhdistetyt kyselyt näytetään tulosjoukossa peräkkäin ilman järjestystä.

Kun yhdistät useamman kuin kaksi kyselyä, voit muuttaa liitosoperaation järjestystä sulkeilla (Kuva 4.4).


Riisi. 4.4

INTERSECT yhdistys

Lause RISTEKSI voit valita vain ne rivit, jotka ovat jokaisessa yhdistettävässä tulosjoukossa. Kuvassa 4.5 näyttää esimerkin kyselyjen yhdistämisestä leikkaaviksi joukoiksi.


Riisi. 4.5.

PAITSI liittyä

Lause PAITSI voit valita vain ne rivit, jotka ovat ensimmäisessä yhdistettävässä tulosjoukossa, mutta eivät toisessa tulosjoukossa.

Lausekkeet RISTEKSI Ja PAITSI tulee tukea vain täydellä SQL-92-standardin mukaisella tasolla. Joten jotkut DBMS:t lauseen sijaan

Oppitunnilla käsitellään liitos-, leikkaus- ja erokyselyoperaatioiden käyttöä. Esimerkkejä sen käytöstä SQL-kysely Union, Exists ja avainsanojen SOME, ANY ja All käyttö. Katettu merkkijonofunktiot


Voit suorittaa liitos-, ero- ja karteesisen tuotteen operaatioita sarjassa. Samoja operaatioita voidaan käyttää sql kyselyt(suorita toimintoja pyyntöjen kanssa).

Erikoissanaa käytetään useiden kyselyjen yhdistämiseen LIITTO.
Syntaksi:

< запрос 1 >UNIONI[KAIKKI]< запрос 2 >

<запрос 1>LIITTO<запрос 2>

Union SQL -kyselyä käytetään yhdistämään kunkin kyselyn tulosrivit yhdeksi tulosjoukoksi.

Jos käytetään parametri ALL, sitten kaikki päällekkäiset tulostusrivit tallennetaan. Jos parametri puuttuu, tulosjoukkoon jää vain yksilölliset rivit.

Voit yhdistää kuinka monta kyselyä tahansa.

UNION-operaattorin käyttö edellyttää useiden ehtojen täyttymistä:

  1. kunkin kyselyn tulossarakkeiden lukumäärän on oltava sama;
  2. kunkin kyselyn tulossarakkeiden on oltava vertailukelpoisia keskenään tietotyypin mukaan (prioriteettijärjestyksessä);
  3. tuloksena oleva joukko käyttää ensimmäisessä kyselyssä määritettyjä sarakkeiden nimiä;
  4. ORDER BY voidaan käyttää vain yhdistetyn kyselyn lopussa, koska se koskee liitoksen tulosta.

Esimerkki: Näytä tietokoneiden ja kannettavien tietokoneiden hinnat sekä niiden numerot (eli kahdesta eri taulukosta yhdellä kyselyllä)


✍ Ratkaisu:
1 2 3 4 5 6 SELECT `Numero` , `Hinta` PC:STÄ UNIONIN VALITSE `Numero` , `Hinta` muistikirjasta TILAA `Hinta`

SELECT `Numero` , `Hinta` PC:STÄ UNIONIN VALITSE `Numero` , `Hinta` muistikirjasta TILAA `Hinta`

Tulos:

Katsotaanpa monimutkaisempaa esimerkkiä, jossa on sisäinen liitos:

Esimerkki: Etsi tuotetyyppi, tietokoneiden ja kannettavien tietokoneiden määrä ja hinta


✍ Ratkaisu:
1 2 3 4 5 6 7 8 VALITSE tuote. `Tyyppi`, pc. `Numero` , `Hinta` PC:STÄ SISÄLIITTYY tuote pc. "Numero" = tuote. `Numero` UNION SELECT tuote. `Tyyppi`, muistikirja. `Numero` , `Hinta` muistikirjasta SISÄLIITÄ tuote kannettavaan. "Numero" = tuote. 'Numero' TILAUS 'Hinnalla'

VALITSE tuote.`Tyyppi` , kpl.`Numero` , `Hinta` PC:STÄ SISÄLIITTYMÄ tuote PC:ssä.`Numero` = tuote.`Numero UNIONIN VALITSE tuote.`Tyyppi` , muistikirja.`Numero`, `Hinta` FROM Notebook INNER JOIN tuote muistikirjaan.`Numero` = tuote.`Numero` TILAUS `Hinta`

Tulos:

SQL Union 1. Löydä kaikkien kannettavien tietokoneiden ja tulostimien valmistaja, osanumero ja hinta

SQL Union 2. Löydä kaikkien Venäjän valmistajan valmistamien tuotteiden numerot ja hinnat

SQL:n olemassaolopredikaatti OLEMASSA

SISÄÄN SQL-kieli On olemassa työkaluja leikkaus- ja erooperaatioiden suorittamiseen kyselyille - INTERSECT-lause (risteys) ja EXCEPT-lause (erotus). Nämä lausekkeet toimivat samalla tavalla kuin UNION toimii: tulosjoukko sisältää vain ne rivit, jotka ovat molemmissa kyselyissä - INTERSECT, tai vain ne ensimmäisen kyselyn rivit, jotka puuttuvat toisesta - EXCEPT. Ongelmana on kuitenkin se, että monet DBMS-järjestelmät eivät tue näitä ehdotuksia. Mutta ulospääsy on olemassa - käyttämällä EXISTS-predikaattia.

EXISTS-predikaatti arvioi arvoon TOSI, jos alikysely palauttaa ainakin osan riveistä; muussa tapauksessa EXISTS antaa arvoksi EPÄTOSI. On myös predikaatti NOT EXISTS, joka toimii päinvastoin.

Yleensä EXISTS-toimintoa käytetään riippuvissa alikyselyissä (esimerkiksi IN).

OLEMASSA (taulukon alikysely)

Esimerkki: Etsi tietokonevalmistajia, jotka valmistavat myös kannettavia tietokoneita


✍ Ratkaisu:

SELECT DISTINCT Manufacturer FROM product AS pc_product WHERE Tyyppi = "Tietokone" JA OLEMASSA (VALITSE Valmistaja FROM tuotteesta WHERE Tyyppi = "Kannettava" JA Valmistaja = pc_product.Manufacturer)

Tulos:

Etsi ne tietokonevalmistajat, jotka eivät valmista tulostimia

SQL JOITAKIN Avainsanat | KAIKKI ja KAIKKI

Avainsanat SOME ja ANY ovat synonyymejä, joten voit käyttää kumpaa tahansa niistä kyselyssäsi. Tällaisen kyselyn tulos on yksi arvosarake.

Syntaksi:

< выражение>< оператор сравнения>JOTKUT | MINKÄ TAHANSA (< подзапрос> )

<выражение><оператор сравнения>JOTKUT | MINKÄ TAHANSA (<подзапрос>)

Jos jollekin alikyselystä palautetulle arvolle X toiminnon " " tulos palauttaa TOSI , niin myös ANY-predikaatti laskee arvoksi TOSI .

Esimerkki: Etsi tietokonetoimittajat, joiden numerot eivät ole myynnissä (eli tietokonetaulukossa)


✍ Ratkaisu:

Taulukon lähdetiedot:

Tulos:

Esimerkissä predikaatti Number = ANY(SELECT Number FROM pc) palauttaa arvon TRUE, kun pääkyselyn Numero löytyy taulukon pc:n numerot -luettelosta (alikysely palauttaa). Lisäksi EI ole käytössä. Tulosjoukko koostuu yhdestä sarakkeesta - Valmistaja. Jotta yksi valmistaja ei näkyisi useita kertoja, otettiin käyttöön palvelusana DISTINCT.
Katsotaan nyt käyttöä avainsana KAIKKI:

Esimerkki: Löydä sellaisten kannettavien tietokoneiden numerot ja hinnat, jotka maksavat enemmän kuin mikään tietokone


✍ Ratkaisu:

Tärkeä: On syytä huomata, että yleensä kysely, jossa on ANY, palauttaa joukon arvoja. Siksi alikyselyn käyttäminen WHERE-lauseessa ilman EXISTS , IN , ALL ja ANY -operaattoreita, jotka tuottavat Boolen arvon, voi johtaa kyselyn ajonaikaiseen virheeseen.


Esimerkki: Etsi sellaisten tietokoneiden numerot ja hinnat, joiden kustannukset ylittävät kannettavien tietokoneiden vähimmäiskustannukset


✍ Ratkaisu:


Tämä kysely on oikea, koska skalaarilauseketta Hinta verrataan alikyselyyn, joka palauttaa yhden arvon

Toiminnot merkkijonojen käsittelyyn SQL:ssä

LEFT-funktio leikkaa merkkien lukumäärän, jonka toinen argumentti määrittää merkkijonon vasemmalta puolelta:

VASEN (<строка>,<число>)

OIKEA-funktio palauttaa määritetyn määrän merkkejä oikealle merkkijonolausekkeesta:

OIKEA(<строка>,<число>)

Esimerkki: Tulosta kaikkien valmistajien nimien ensimmäiset kirjaimet


✍ Ratkaisu:

SELECT DISTINCT LEFT(`Manufacturer` , 1) FROM `product`

Tulos:

Esimerkki: Tulosta valmistajien nimet, jotka alkavat ja päättyvät samalla kirjaimella


✍ Ratkaisu:

SQL-korvaustoiminto

Syntaksi:

SELECT `nimi` , REPLACE(`nimi` , "a", "aa") FROM `opettajista`