Introductie
Als u werkt met relationele databases en Structured Query Language (SQL), kunnen er momenten zijn waarop u moet werken met waarden die specifieke datums of tijden vertegenwoordigen. U moet bijvoorbeeld het totale aantal uren berekenen dat aan een bepaalde activiteit is besteed, of misschien moet u datums of tijden manipuleren met behulp van wiskundige operatoren en aggregatiefuncties om hun som of gemiddelde te berekenen.
In deze zelfstudie leert u hoe u datums en tijden kunt gebruiken in SQL. U begint met het uitvoeren van rekenkundige bewerkingen en het gebruiken van verschillende functies met datums en tijden met alleen de SELECT
-verklaring. Vervolgens oefent u door vragen uit te voeren op voorbeeldgegevens, en leert u hoe u de CAST
-functie kunt implementeren om de uitvoer gemakkelijker leesbaar te maken.
Vereisten
Om deze zelfstudie te voltooien, heeft u nodig:
- A server running Ubuntu 20.04, with a non-root user with
sudo
administrative privileges and firewall enabled. Follow our Initial Server Setup with Ubuntu 20.04 to get started. - MySQL geïnstalleerd en beveiligd op de server. Volg onze handleiding Hoe MySQL te installeren op Ubuntu 20.04 om dit in te stellen. Deze handleiding gaat ervan uit dat u ook een niet-root MySQL-gebruiker hebt ingesteld, zoals beschreven in Stap 3 van deze handleiding.
Let op: Houd er rekening mee dat veel relationele databasebeheersystemen hun eigen unieke implementaties van SQL gebruiken. Hoewel de commando’s die in deze tutorial worden beschreven op de meeste RDBMS’en zullen werken, kan de exacte syntaxis of uitvoer verschillen als je ze test op een ander systeem dan MySQL.
Om te oefenen met het gebruik van datum en tijd in deze tutorial, heb je een database en een tabel nodig die zijn geladen met voorbeeldgegevens. Als je er geen klaar hebt om in te voegen, kun je de volgende Verbinding maken met MySQL en een voorbeelddatabase instellen sectie lezen om te leren hoe je een database en tabel kunt maken. In deze tutorial wordt voortdurend verwezen naar deze voorbeelddatabase en -tabel.
Verbinding maken met MySQL en een voorbeelddatabase instellen
Als je SQL-database op een externe server wordt uitgevoerd, maak dan verbinding met je server vanaf je lokale machine via SSH:
Vervolgens open je de MySQL-prompt, waarbij je sammy
vervangt door jouw MySQL-gebruikersaccountinformatie:
Maak een database met de naam datetimeDB
:
Als de database succesvol is aangemaakt, ontvang je de volgende uitvoer:
OutputQuery OK, 1 row affected (0.01 sec)
Om de database datetimeDB
te selecteren, voer je het volgende USE
-statement uit:
OutputDatabase changed
Na het selecteren van de database, maak een tabel erin aan. Voor het voorbeeld van deze tutorial zullen we een tabel maken die de resultaten van twee hardlopers bij verschillende races gedurende een jaar bevat. Deze tabel zal de volgende zeven kolommen bevatten:
race_id
: toont waarden van het datatypeint
en dient als de primaire sleutel van de tabel, wat betekent dat elke waarde in deze kolom zal functioneren als een unieke identifier voor de respectievelijke rij.runner_name
: gebruikt het datatypevarchar
met een maximum van 30 tekens voor de namen van de twee hardlopers, Bolt en Felix.race_name
: bevat de typen races met het datatypevarchar
met een maximum van 20 tekens.start_day
: gebruikt het datatypeDATE
om de datum van een specifieke race bij te houden op jaar-, maand- en dagbasis. Dit datatype volgt de volgende parameters: vier cijfers voor het jaar en maximaal twee cijfers voor de maand en dag (YYYY-MM-DD
).start_time
: vertegenwoordigt de starttijd van de race met het datatypeTIME
op basis van uren, minuten en seconden (HH:MM:SS
). Dit datatype volgt een 24-uursklokformaat, zoals15:00
voor het equivalent van 15:00 uur.total_miles
: toont het totale aantal kilometers voor elke race met het gegevenstypedecimal
, aangezien veel van de totale kilometers per race geen gehele getallen zijn. In dit geval geeftdecimal
een precisie van drie met een schaal van één aan, wat betekent dat alle waarden in deze kolom drie cijfers kunnen hebben, waarvan één cijfer rechts van het decimaalteken staat.end_time
: gebruikt het gegevenstypeTIMESTAMP
om de eindtijden van de hardlopers bij te houden. Dit gegevenstype combineert zowel datum als tijd in één string, en het formaat is een combinatie van die vanDATE
enTIME
: (YYYY-MM-DD HH:MM:SS
).
Maak de tabel door het CREATE TABLE
commando uit te voeren:
Voeg vervolgens wat voorbeeldgegevens toe aan de lege tabel:
OutputQuery OK, 10 rows affected (0.00 sec)
Records: 10 Duplicates: 0 Warnings: 0
Zodra u de gegevens hebt ingevoegd, bent u klaar om wat rekenkundige bewerkingen en functies met datum en tijd in SQL te oefenen.
Het gebruik van Rekenkundige bewerkingen met Datums en Tijden
In SQL kunt u datum- en tijdwaarden manipuleren met wiskundige expressies. Het enige wat nodig is, is de wiskundige operator en de waarden die u wilt berekenen.
Als voorbeeld, stel dat je één datum wilt vinden die een bepaald aantal dagen na een andere datum ligt. De volgende query neemt één datumwaarde (2022-10-05
) en telt er 17
bij op om de waarde voor de datum zeventien dagen na de gespecificeerde datum in de query terug te geven. Let op dat dit voorbeeld 2022-10-05
specificeert als een DATE
-waarde om ervoor te zorgen dat het DBMS het niet interpreteert als een tekenreeks of een ander gegevenstype:
Output+----------+
| new_date |
+----------+
| 20221022 |
+----------+
1 row in set (0.01 sec)
Zoals deze uitvoer aangeeft, is 17 dagen na 2022-10-05
2022-10-22
, of 22 oktober 2022.
Als een ander voorbeeld, stel dat je het totale aantal uren tussen twee verschillende tijden wilt berekenen. Dit kun je doen door de twee tijden van elkaar af te trekken. Voor de volgende query is 11:00
de eerste tijdwaarde en 3:00
is de tweede tijdwaarde. Hier moet je aangeven dat beide TIME
-waarden zijn om het verschil in uren terug te geven:
Output+-----------+
| time_diff |
+-----------+
| 80000 |
+-----------+
1 row in set (0.00 sec)
Deze uitvoer vertelt je dat het verschil tussen 11:00 en 3:00 80000
is, ofwel 8 uur.
Oefen nu met het gebruik van rekenkundige bewerkingen op de datum- en tijdinformatie uit de voorbeeldgegevens. Voor de eerste query, bereken de totale tijd die de hardlopers nodig hadden om elke race te voltooien door end_time
van start_time
af te trekken:
Output+-------------+---------------+----------------+
| runner_name | race_name | total_time |
+-------------+---------------+----------------+
| bolt | 1600_meters | 20220918000630 |
| bolt | 5K | 20221019002231 |
| bolt | 10K | 20221120003805 |
| bolt | half_marathon | 20221221013904 |
| bolt | full_marathon | 20230122032310 |
| felix | 1600_meters | 20220918000715 |
| felix | 5K | 20221019003050 |
| felix | 10K | 20221120011017 |
| felix | half_marathon | 20221221021157 |
| felix | full_marathon | 20230122040210 |
+-------------+---------------+----------------+
10 rows in set (0.00 sec)
Je zult merken dat de uitvoer in de total_time
-kolom vrij lang en moeilijk leesbaar is. Later zullen we demonstreren hoe je de CAST
-functie kunt gebruiken om deze gegevenswaarden om te zetten zodat ze duidelijker te lezen zijn.
Nu, als je alleen geïnteresseerd was in de prestaties van elke hardloper voor langere races, zoals de halve en hele marathons, kun je je gegevens bevragen om die informatie op te halen. Voor deze query trek je end_time
af van start_time
, en beperk je je resultaten door de WHERE
-clausule te gebruiken om gegevens op te halen waar total_miles
groter waren dan 12:
Output+-------------+---------------+-------------------+
| runner_name | race_name | half_full_results |
+-------------+---------------+-------------------+
| bolt | half_marathon | 20221221013904 |
| bolt | full_marathon | 20230122032310 |
| felix | half_marathon | 20221221021157 |
| felix | full_marathon | 20230122040210 |
+-------------+---------------+-------------------+
4 rows in set (0.00 sec)
In dit gedeelte heb je enkele berekeningen uitgevoerd met datums en tijden met de SELECT
-verklaring en voor praktische doeleinden op de voorbeeldgegevens. Hierna zul je oefenen met queries met behulp van verschillende datum- en tijdfuncties.
Het gebruik van datum- en tijdfuncties en intervaluitdrukkingen
Er zijn verschillende functies die kunnen worden gebruikt om datum- en tijdwaarden te vinden en te manipuleren in SQL. SQL-functies worden meestal gebruikt om gegevens te verwerken of te manipuleren, en de beschikbare functies zijn afhankelijk van de SQL-implementatie. De meeste SQL-implementaties laten echter toe dat je de huidige datum en tijd vindt door te zoeken naar de waarden current_date
en current_time
.
Om bijvoorbeeld de datum van vandaag te vinden, is de syntaxis kort en bestaat alleen uit de SELECT
-verklaring en de functie current_date
zoals in het volgende:
Output+--------------+
| current_date |
+--------------+
| 2022-02-15 |
+--------------+
1 row in set (0.00 sec)
Met dezelfde syntaxis kun je de huidige tijd vinden met de functie current_time
:
Output+--------------+
| current_time |
+--------------+
| 17:10:20 |
+--------------+
1 row in set (0.00 sec)
Als je liever zowel datum als tijd in de output wilt opvragen, gebruik dan de functie current_timestamp
:
Output+---------------------+
| current_timestamp |
+---------------------+
| 2022-02-15 19:09:58 |
+---------------------+
1 row in set (0.00 sec)
Je kunt datum- en tijdfuncties zoals deze gebruiken binnen rekenkundige functies vergelijkbaar met de vorige sectie. Bijvoorbeeld, stel dat je wilt weten wat de datum was 11 dagen geleden vanaf de datum van vandaag. In dit geval zou je dezelfde syntaxisstructuur kunnen gebruiken als eerder om de functie current_date
op te vragen en er vervolgens 11
van af te trekken om de datum van elf dagen geleden te vinden:
Output+-------------------+
| current_date - 11 |
+-------------------+
| 20220206 |
+-------------------+
1 row in set (0.01 sec)
Zoals deze output aangeeft, was het 11 dagen geleden vanaf de current_date
(op het moment van schrijven) 2022-02-06
, ofwel 6 februari 2022. Probeer nu dezelfde bewerking uit te voeren, maar vervang current_date
door de functie current_time
:
Output+-------------------+
| current_time - 11 |
+-------------------+
| 233639 |
+-------------------+
1 row in set (0.00 sec)
Deze output toont aan dat wanneer je 11
aftrekt van de waarde van current_time
, het 11 seconden aftrekt. De bewerking die je eerder uitvoerde met de functie current_date
interpreteerde 11
als dagen, niet als seconden. Deze inconsistentie in hoe getallen worden geïnterpreteerd bij het werken met datum- en tijdfuncties kan verwarrend zijn. In plaats van dat je datum- en tijdwaarden moet manipuleren met rekenkundige bewerkingen zoals deze, laten veel databasebeheersystemen je explicieter zijn door het gebruik van INTERVAL
-expressies.
INTERVAL
-expressies stellen je in staat om te vinden wat de datum of tijd zou zijn voor of na een ingesteld interval vanaf een gegeven datum- of tijdexpressie. Ze moeten de volgende vorm hebben:
INTERVAL value unit
Om bijvoorbeeld de datum vijf dagen vanaf nu te vinden, zou je de volgende query kunnen uitvoeren:
Dit voorbeeld vindt de waarde van current_date
en voegt vervolgens de intervaluitdrukking INTERVAL '5' DAY
eraan toe. Dit geeft de datum 5 dagen vanaf nu terug:
Output+-------------------+
| 5_days_from_today |
+-------------------+
| 2022-03-06 |
+-------------------+
1 row in set (0.00 sec)
Dit is veel minder ambigu dan de volgende query, die een vergelijkbare, zij het niet identieke, output produceert:
Output+-------------------+
| 5_days_from_today |
+-------------------+
| 20220306 |
+-------------------+
1 row in set (0.00 sec)
Merk op dat je ook intervallen van datums of tijden kunt aftrekken om waarden van voor de opgegeven datumwaarde te vinden:
Output+--------------+
| 7_months_ago |
+--------------+
| 2021-08-01 |
+--------------+
1 row in set (0.00 sec)
Welke eenheden beschikbaar zijn voor gebruik in INTERVAL
-expressies, hangt af van je keuze van DBMS, hoewel de meeste opties zoals UUR
, MINUUT
en SECONDE
zullen hebben:
Output+------------------+---------------+---------------------+
| 6_hours_from_now | 5_minutes_ago | 20_seconds_from_now |
+------------------+---------------+---------------------+
| 07:51:43 | 01:46:43 | 01:52:03.000000 |
+------------------+---------------+---------------------+
1 row in set (0.00 sec)
Nu je meer hebt geleerd over intervaluitdrukkingen en enkele datum- en tijdfuncties, ga je verder met oefenen met het werken met de voorbeeldgegevens die je hebt ingevoegd in de eerste stap.
Het gebruik van CAST en Aggregaatfuncties met Datum en Tijd
Herinner je je de derde voorbeeldquery uit de sectie Het gebruik van Rekenkunde met Datums en Tijden, toen je de volgende query uitvoerde om eindtijd
van starttijd
af te trekken om het totale aantal uren te berekenen dat elke hardloper per race heeft voltooid. De output resulteerde echter in een kolom met een zeer lange output, die volgt op het TIMESTAMP
-gegevenstype dat in de tabel was ingesteld:
Output+-------------+---------------+----------------+
| runner_name | race_name | total_time |
+-------------+---------------+----------------+
| bolt | 1600_meters | 20220918000630 |
| bolt | 5K | 20221019002231 |
| bolt | 10K | 20221120003805 |
| bolt | half_marathon | 20221221013904 |
| bolt | full_marathon | 20230122032310 |
| felix | 1600_meters | 20220918000715 |
| felix | 5K | 20221019003050 |
| felix | 10K | 20221120011017 |
| felix | half_marathon | 20221221021157 |
| felix | full_marathon | 20230122040210 |
+-------------+---------------+----------------+
10 rows in set (0.00 sec)
Omdat je een bewerking uitvoert met twee kolommen die verschillende gegevenstypen hebben (end_time
die TIMESTAMP
-waarden bevat en start_time
die TIME
-waarden bevat), weet de database niet welk gegevenstype moet worden gebruikt wanneer het resultaat van de bewerking wordt afgedrukt. In plaats daarvan worden beide waarden omgezet naar gehele getallen zodat de bewerking kan worden uitgevoerd, wat resulteert in de lange getallen in de kolom total_time
.
Om deze gegevens duidelijker te maken om te lezen en te interpreteren, kun je de CAST
-functie gebruiken om deze lange gehele getalwaarden om te zetten naar het gegevenstype TIME
. Om dit te doen, begin met CAST
en volg dit direct met een opening haakje, de waarden die je wilt converteren, en vervolgens het AS
-sleutelwoord en het gegevenstype waarnaar je het wilt converteren.
De volgende query is identiek aan het vorige voorbeeld, maar gebruikt een CAST
-functie om de kolom total_time
naar het gegevenstype time
te converteren:
Output+-------------+---------------+------------+
| runner_name | race_name | total_time |
+-------------+---------------+------------+
| bolt | 1600_meters | 00:06:30 |
| bolt | 5K | 00:22:31 |
| bolt | 10K | 00:38:05 |
| bolt | half_marathon | 01:39:04 |
| bolt | full_marathon | 03:23:10 |
| felix | 1600_meters | 00:07:15 |
| felix | 5K | 00:30:50 |
| felix | 10K | 01:10:17 |
| felix | half_marathon | 02:11:57 |
| felix | full_marathon | 04:02:10 |
+-------------+---------------+------------+
10 rows in set (0.00 sec)
CAST
heeft de gegevenswaarden in deze uitvoer omgezet naar TIME
, waardoor het veel gemakkelijker te lezen en te begrijpen is.
Nu, laten we een paar aggregatiefuncties gebruiken in combinatie met de CAST
-functie om de kortste, langste en totale tijdresultaten van elke loper te vinden. Eerst, vraag naar de minimum (of kortste) hoeveelheid tijd besteed met de MIN
-aggregatiefunctie. Opnieuw, zul je CAST
willen gebruiken om de TIMESTAMP
-gegevenswaarden naar TIME
-gegevenswaarden om te zetten voor duidelijkheid. Let op dat bij het gebruik van twee functies zoals in dit voorbeeld, twee paren van haakjes nodig zijn en de berekening voor het totale aantal uren (eindtijd - starttijd
) genest moet worden binnen één ervan. Voeg ten slotte een GROUP BY
clausule toe om deze waarden te organiseren op basis van de runner_name
-kolom zodat de output de raceresultaten van de twee lopers zal presenteren:
Output+-------------+----------+
| runner_name | min_time |
+-------------+----------+
| bolt | 00:06:30 |
| felix | 00:07:15 |
+-------------+----------+
2 rows in set (0.00 sec)
Deze output toont de kortste looptijd van elke loper, in dit geval een minimum van zes minuten en 30 seconden voor Bolt, en zeven minuten en 15 seconden voor Felix.
Volgende, vind de langste looptijd van elke loper. Je kunt dezelfde syntaxis gebruiken als de vorige query, maar vervang deze keer MIN
door MAX
:
Output+-------------+----------+
| runner_name | max_time |
+-------------+----------+
| bolt | 03:23:10 |
| felix | 04:02:10 |
+-------------+----------+
2 rows in set (0.00 sec)
Deze output vertelt ons dat de langste looptijd van Bolt een totaal van drie uur, 23 minuten en 10 seconden was; en die van Felix was een totaal van vier uur, twee minuten en 10 seconden.
Nu laten we een query uitvoeren voor wat hoog-niveau informatie over het totale aantal uren dat elke hardloper aan het hardlopen besteedde. Voor deze query combineer de SUM
aggregatiefunctie om de totale som van uren te vinden op basis van eindtijd - starttijd
, en gebruik CAST
om die gegevenswaarden om te zetten naar TIME
. Vergeet niet GROUP BY
op te nemen om de waarden te organiseren voor zowel de resultaten van de hardlopers:
Output+-------------+-------------+
| runner_name | total_hours |
+-------------+-------------+
| bolt | 52880 |
| felix | 76149 |
+-------------+-------------+
2 rows in set (0.00 sec)
Interessant is dat deze uitvoer de interpretatie voor MySQL laat zien, die eigenlijk de totale tijd berekent als gehele getallen. Als we deze resultaten als tijd lezen, wordt de totale tijd van Bolt opgesplitst in vijf uur, 28 minuten en 80 seconden; en de tijd van Felix wordt opgesplitst in zeven uur, 61 minuten en 49 seconden. Zoals je kunt zien, heeft deze tijdsverdeling geen zin, wat aangeeft dat het als een geheel getal wordt berekend en niet als tijd. Als je dit in een ander DBMS zou proberen, zoals PostgreSQL, zou dezelfde query er iets anders uitzien:
Output runner_name | total_hours
-------------+-------------
felix | 10:01:44
bolt | 06:09:20
(2 rows)
In dit geval interpreteert de query in PostgreSQL de waarden als tijd en berekent deze ook als zodanig, zodat de resultaten van Felix worden opgesplitst in een totaal van 10 uur, één minuut en 44 seconden; en die van Bolt als zes uur, negen minuten en 20 seconden. Dit is een voorbeeld van hoe verschillende implementaties van DBMS gegevenswaarden anders kunnen interpreteren, zelfs als dezelfde query en dataset worden gebruikt.
Conclusie
Het begrijpen van hoe je datum en tijd in SQL gebruikt is handig bij het opvragen van specifieke resultaten zoals minuten, seconden, uren, dagen, maanden, jaren; of een combinatie van al deze. Bovendien zijn er veel functies beschikbaar voor datums en tijden die het gemakkelijker maken om bepaalde waarden te vinden, zoals de huidige datum of tijd. Hoewel deze handleiding alleen gebruik maakte van optel- en aftrekaritmetiek op datums en tijden in SQL, kun je datum- en tijdwaarden gebruiken met elke wiskundige expressie. Leer meer vanuit onze gids over wiskundige expressies en aggregatiefuncties en probeer ze uit met je datum- en tijdquery’s.
Source:
https://www.digitalocean.com/community/tutorials/how-to-work-with-dates-and-times-in-sql