SQL - basale udtryk
|
<< Click to Display Table of Contents >> SQL - basale udtryk |
![]() ![]()
|
Simpel SELECT
Forespørsler starter altid med kommandoen SELECT.
Efter SELECT anføres de ønskede feltnavne fulgt af datakilden (f.eks. en tabel):
SELECT t01.feltnavn01, t01.feltnavn02, t01.feltnavn03
FROM tabelnavn01 t01
hvor tabelnavnet her er givet et kort ad hoc alias (t01), der foran hvert feltnavn anføres som præcisering af feltnavnets oprindelse, hvilket er optionelt men en generelt god skik og en nødvendighed, hvis der forespørges til flere tabeller, der hver indeholder samme feltnavne.
Ved forespørgsler på flere tabeller, kobles forespørgslen sammen med med udtrykket JOIN tabel02 ON tabel02.feltnavn = tabel01.feltnavn som i:
SELECT t01.feltnavn01, t02.feltnavn02, t02.feltnavn03
FROM tabelnavn01 t01 JOIN tabelnavn02 t02 ON t02.feltnavn01 = t01.feltnavn01
hvor feltnavn01 i hver tabel bruges til at matche samhørende data fra de to tabeller, og hvor feltnavn01 f.eks. kunne være et person-ID.
F.eks. som i:
SELECT t01.Fornavn, t01.Efternavn, t02.AmbDato
FROM tabelnavn01 t01 JOIN tabelnavn02 t02 ON t02.PersonID = t01.PersonID
Simpel SELECT med selektions-filtre
Selv ved det simpleste udtræk vil man ofte tilføje et eller andet selektionskriterie, der angives ved betingelsen WHERE (eller HAVING, derom senere):
SELECT t01.Fornavn, t01.Efternavn, t02.AmbDato
FROM tabelnavn01 t01 JOIN tabelnavn02 t02 ON t02.PersonID = t01.PersonID
WHERE t02.AmbDato > NOW
der som hér begrænser datoer til kun fremtidige datoer.
Simpel SELECT med sortering
Oftest vil man udover selve udtrækket også tilføje en eller anden hensigtsmæssig sortering v.h.a. udtrykket ORDER BY, der altid skal stå sidst i udtrykket som i:
SELECT t01.Fornavn, t01.Efternavn, t02.AmbDato
FROM tabelnavn01 t01 JOIN tabelnavn02 t02 ON t02.PersonID = t01.PersonID
WHERE t02.AmbDato > NOW
ORDER BY t01.Fornavn, t01.Efternavn, t02.AmbDato
eller som i:
SELECT t01.Fornavn, t01.Efternavn, t02.AmbDato
FROM tabelnavn01 t01 JOIN tabelnavn02 t02 ON t02.PersonID = t01.PersonID
WHERE t02.AmbDato > NOW
ORDER BY t02.AmbDato, t01.Fornavn, t01.Efternavn
Simpel SELECT med sammentælling
Udtryk, der sammentæller værdier som antal værdier, sum af værdier, gennemsnit, m.v. kaldes fælles aggregations-forespørgsler.
Hvis AmbDato står for ambulant dato kunne man f.eks. udtrække hvor mange ambulante datoer personerne har haft:
SELECT t01.Fornavn, t01.Efternavn, COUNT(t02.AmbDato) AS "AmbDatoer"
FROM tabelnavn01 t01 JOIN tabelnavn02 t02 ON t02.PersonID = t01.PersonID
WHERE t02.AmbDato < CAST(NOW AS DATE)
GROUP BY t01.Fornavn, t01.Efternavn
ORDER BY [AmbDatoer], t01.Fornavn, t01.Efternavn
hvor enhvert sådan aggregations-forespørgsel fordrer, at der angives et GROUP BY på alle de felter, der ikke aggregeres, og hvor GROUP BY altid skal stå før (over) en eventuel sorteringskommando (ORDER BY).
Da sammentællingen af antal ambulante datoer i sig selv er en ny parameter, er denne parameter givet navnet "AmbDatoer" angivet ved AS "AmbDatoer".
Sekundære referencer til afledte parametre som f.eks. her AmbDatoer kan være lidt forskellig i diverse databaser, men vil oftest have en særlig afgrænser for at markere, at den ikke skal søges blandt de primære feltnavne (tabellers kolonnenavne), og hvor den som her refereres v.h.a. kantede parenteser.
P.S.: Når der som hér er indsat datakonverteringen CAST(NOW AS DATE) er det fordi NOW også indeholder tider, hvorved NOW altid vil være større end selve datoværdien for dags-dato. Som udgangspunkt er valgt NOW, da den tilsvarende funktion for dags-dato er forskellig fra database til database (DATE, CURRENT_DATE, etc.).
Simpel SELECT - WHERE vs. HAVING
Udover betingelsesfiltre på originaldata, der angives ved betingelsen WHERE, kan man også filtrere med betingelser på resultatet af en aggregation, der adskiller sig fra førnævnte ved at være angivet med betingelsen HAVING, der altid skal ligge efter GROUP BY og før en optionel ORDER BY.
Man kunne f.eks. forspørge om antallet af ambulante datoer for dem, der fremtidigt har mere end een ambulant dato som i:
SELECT t01.PersonID, t01.Fornavn, t01.Efternavn, COUNT(t02.AmbDato) AS "AntalDatoer"
FROM tabelnavn01 t01 JOIN tabelnavn02 t02 ON t02.PersonID = t01.PersonID
WHERE t02.AmbDato > NOW
GROUP BY t01.PersonID, t01.Fornavn, t01.Efternavn
HAVING [AntalDatoer] > 1
ORDER BY t01.Fornavn, t01.Efternavn
Hvis man ønsker at hente de specifikke datoer for ovennævnte, er det nødvendigt med en sub-query som f.eks:
SELECT t01.PersonID, t01.Fornavn, t01.Efternavn, t02.AmbDato
FROM tabelnavn01 t01 JOIN tabelnavn02 t02
ON t02.PersonID = t01.PersonID
JOIN
(SELECT st02.PersonID, COUNT(st02.AmbDato) AS "AntalDatoer"
FROM tabelnavn02 st02
WHERE st02.AmbDato > NOW
GROUP BY st02.PersonID
HAVING COUNT(st02.AmbDato) > 1)
ON st02.PersonID = t01.PersonID
WHERE t02.AmbDato > NOW
ORDER BY t01.PersonID, t01.Fornavn, t01.Efternavn, t02.AmbDato;
SELECT eller SELECT DISTINCT ?
Hvis man vil forespørge, hvem der har ambulante datoer aftaler indenfor den næste måned, kunne man spørge:
SELECT t01.PersonID, t01.Fornavn, t01.Efternavn, t02.AmbDato
FROM tabelnavn01 t01 JOIN tabelnavn02 t02 ON t02.PersonID = t01.PersonID
WHERE ((t02.AmbDato > NOW) AND (t02.AmbDato <= (NOW + 31)))
ORDER BY t02.AmbDato, t01.PersonID, t01.Fornavn, t01.Efternavn
der p.g.a. datoerne for personer med flere aftalte fremmøder vil give distinkte værdier for disse, men hvis man kun forespurgte på hvem der har aftaler den kommende måned men ikke de specifikke datoer, vil man for dem med flere aftaler få duplikate værdier (rækker), der godt nok dækker over bagvedliggende forskellige datoer.
Det anførte interval-kriterium kunne også udtrykkes via prædiakatet BETWEEN, der inkluderer begge yderværdier, som i:
SELECT t01.PersonID, t01.Fornavn, t01.Efternavn, t02.AmbDato
FROM tabelnavn01 t01 JOIN tabelnavn02 t02 ON t02.PersonID = t01.PersonID
WHERE t02.AmbDato BETWEEN (CAST(NOW AS DATE) + 1) AND (CAST(NOW AS DATE) + 31)
ORDER BY t02.AmbDato, t01.PersonID, t01.Fornavn, t01.Efternavn
For at udelade sammenlægge duplikate udlæsninger kan man efter SELECT tilføje prædikatet DISTINCT, der udelader duplikate rækker i det udlæste:
SELECT DISTINCT t01.PersonID, t01.Fornavn, t01.Efternavn
FROM tabelnavn01 t01 JOIN tabelnavn02 t02 ON t02.PersonID = t01.PersonID
WHERE t02.AmbDato BETWEEN (CAST(NOW AS DATE) + 1) AND (CAST(NOW AS DATE) + 31)
ORDER BY t01.PersonID, t01.Fornavn, t01.Efternavn
Funktionen af prædikatet DISTINCT er altså helt afhængig af hvilke felter man har valgt medtaget i sit udtræk.
_____________________________
27-10-2017 - © 2003-2017 Niels Knabe