PARTE SECONDA

Riepilogo Parte Prima.

Abbiamo visto le caratteristiche dei campi in formato data/ora di MySQL.
MySQL e' molto flessibile nella gestione delle date. Permette di copiare, inserire
calcolare anche al di fuori del formato date/time. Molta flessibilita' significa piu'
controllo delle congruenze per il softwerista. Un formato errato si tradurra'
in una sequenza di zeri. Se questo formato errato lo inserite, in un campo con
formato INT, char/varchar questo verra' scritto, ma continuera' ad essere un formato
errato e quindi inservibile alle funzioni MySQL.

Da notare inoltre, che ogni formato ha un diverso range di validita', e' possibile
copiare, calcolare dati tra un campo e l'altro mantenendo i valori iniziali,
ma la congruenza del range e/o del tipo di formato la dovrete fare voi. Se non sara'
corretto, MySQL non segnalera' errori, ma mettera' semplicemente una bella serie
di zeri al posto di...

MySQL possiede una buona scelta di funzioni date/time che e' possibile utilizzare
nelle query alle sezioni INSERT, UPDATE, SELECT e WHERE.

Un primo gruppo rappresenta le funzioni che rendono la data e/o l'ora senza alcuna
manipolazione dei dati e con argomento della funzione = VOID.

A)Funzioni di MySQL per l'estrazione di dati DATE/TIME (VOID).

NOW()
SYSDATE()
CURRENT_TIMESTAMP


Sono in pratica equivalenti. Vediamo, estensibili a tutti, le caratteristiche di NOW()
che e' presente nel menu' PhpMyAdmin. La funzione NOW() acquisisce data/ora di sistema
una sola volta all'inizio della query, quindi il valore ottenuto verra' utilizzato per
soddisfare tutte le richieste della query stessa. Aggiorna automaticamente un solo
campo formato TIMESTAMP, il primo in ordine di posizione nella lista dei campi della
tabella. Gli altri campi presenti nello stesso record con formato TIMESTAMP verranno
aggiornati solo su esplicita richiesta della query.

Le tre funzioni sopra elencate, rendono sempre data/ora secondo il seguente formato:
'YYYY-MM-DD HH:MM:SS' frm. stringa oppure YYYYMMDDHHMMSS frm. numerico. La forma
dipendera' dal tipo di campo che ricevera' il dato. E' possibile forzare un formato
numerico nella risposta sommando uno zero oppure moltiplicando * 1 la data richiesta.
Se il campo non e' dimensionato a sufficienza oppure e' un campo con dati TIME o
DATE i dati superflui o eccedenti il campo verranno persi. Fa eccezione il formato
TIMESTAMP, come visto nella parte prima, che conserva sempre tutti i dati inseriti.

SELECT NOW() => 2003-05-20 17:29:09
SELECT NOW() + 0 => 20030520190137 Forzare una risposta numerica
SELECT * FROM tabella WHERE nome_campo = NOW()
UPDATE tabella SET data=NOW() where data < NOW() Aggiorna ad oggi un campo data.
UPDATE tabella SET scadenza = data + INTERVAL 1 MONTH WHERE id = $id.
Mettera' nel campo 'scadenza' la data memorizzata nel campo 'data' + un mese
DELETE FROM tabella where scadenza < NOW() Cancella record scaduti



CURRENT_DATE - CURDATE()
CURRENT_TIME - CURTIME()


Queste 4 (anzi 2) funzioni forniscono rispettivamente solo la data, e solo l'ora.
Sono i fratelli minori delle funzioni viste prima. Vengono utilizzati quando serve
avere o solo la data oppure soltanto l'ora.

SELECT CURDATE() => 2003-05-20 abbiamo la data senza l'ora.
SELECT CURTIME() => 22:19:50 abbiamo l'ora senza la data.
SELECT CURDATE() + 0 => 20030520 data senza ora in formato numerico.
SELECT CURTIME() * 1 => 221950 ora senza data in formato numerico.



B)Funzioni di MySQL per l'estrazione mirata di dati DATE/TIME.

Vediamo quali sono, a che servono e qualche esempio di applicazione.

1) - Informazioni sul giorno.

Se abbiamo bisogno di estrarre un giorno da una data, abbiamo disponibili ben 4
specifiche funzioni:

DAYOFYEAR(data)
DAYOFMONTH(data)
DAYOFWEEK(data)
WEEKDAY(data)


DAYOFYEAR - Da come risultato in formato numerico, il giorno dell'anno
estraendolo da una data . Cioe' rende il numero dei giorni passati a partire dal
1 Gennaio di un determinato anno.

funziona cosi':
SELECT DAYOFYEAR("2003-05-20") => 140 140° giorno dell'anno 2003
SELECT DAYOFYEAR("2000/05/20") => 141 141° nel 2000 perche' bisestile.
SELECT DAYOFYEAR("20030520") => 140 140° giorno dell'anno 2003
SELECT DAYOFYEAR("00-05-20") => 141 141° giorno dell'anno 2000
SELECT DAYOFYEAR(NOW()) => 140 140° alla data del 20-05-2003
SELECT DAYOFYEAR(CURDATE()) => 140 140° giorno dell'anno 2003
SELECT DAYOFYEAR(nome_campo) from tabella dove nome_campo contiene una data valida

ma non cosi', anche se la query non dara' segnalazioni di errore:

SELECT DAYOFYEAR("20-05-2003") as data => 141 interpreta 2020-05-20(03 eccedenti)
SELECT DAYOFYEAR(CURTIME()) => NULL Perche' CURTIME contiene solo l'ora.
SELECT DAYOFYEAR(2003-05-20) => NULL Perche' mancano gli apici all'argomento.

Negli esempi che seguiranno si alterneranno le varie forme possibili di inserimento
della data da analizzare. Si tenga presente che le regole sopra esposte sono
applicabili per tutte le funzioni che vedremo.


DAYOFMONTH - Da come risultato in formato numerico, il giorno del mese
estraendolo da una data. Cioe' rende il numero dei giorni passati a partire dal
giorno 1 di un determinato mese.

SELECT DAYOFMONTH("2003-05-20") => 20 20° giorno del mese di Maggio/2003


DAYOFWEEK - Da come risultato in formato numerico, il giorno della
settimana estraendolo da una data. L'indice dei giorni che viene fornito e'
conforme allo standard ODBC. L'indice inizia con:
1 = domenica, 2 = lunedi', 3 = martedi'.... ecc.

SELECT DAYOFWEEK("2003-05-20") => 3 martedi' 3° giorno della settimana
SELECT * FROM order WHERE dayofweek(data_order)=2; =>Gli ordini del lunedì.


WEEKDAY - E molto simile a DAYOFWEEK ma rende un indice diverso per
i giorni della settimana, sempre estratti da una data:
0 = Lunedi', 1= martedi',2 = martedi', 3= mercoledi' ....ecc.

SELECT WEEKDAY("2003-05-20") => 1 indice 1 del giorno martedi'


2) Estrazione Anni, Trimestri, Mesi, Settimane. Nome dei mesi e giorni.

Anche queste funzioni lavorano a partire da una data.
Data, ricordiamo, in qualsiasi formato ammesso.

YEAR(date)
QUARTER(date)
MONTH(date)
WEEK(date[, primogiorno])
YEARWEEK(date[,primogiorno]
MONTHNAME(date)
DAYNAME(date)



YEAR(date) - Estrae l'anno da una data in formato numerico di 4 digit.

SELECT YEAR(NOW()); 2003 Anno corrente.
SELECT * FROM tabella WHERE YEAR(campo_data) < 2003


QUARTER(date) - Rende il n. del trimestre da una data inserita.
Valori: 1=I° trimestre, 2=secondo, 3=terzo, 4=quarto.

SELECT QUARTER(NOW()); => 2 Secondo TRIMESTRE 2003.
SELECT * FROM tabella where QUARTER(campo_data) = 2 AND YEAR(campo_data)= 2003;
Rendera' tutti i record con data inserita nel II trimestre 2003.


MONTH(date) - Da come risultato il n. del mese estratto da una data,
nell'intervallo 1-12.

SELECT MONTH(NOW()); => 5 n. del mese di maggio.
SELECT * FROM tabella WHERE MONTH(campo_data) = 5 AND YEAR(campo_data)= 2003;
Rendera' tutti i record con data inserita nel maggio 2003.


WEEK(date) - YEARWEEK(date) - Queste due funzioni rendono il numero della
settimana da una data dell'anno. Il secondo parametro "first" serve ad indicare
se la settimana inizia di domenica (0) oppure Lunedi'(1). Il comportamento differisce
nel modo di presentare i dati. WEEK() ha un range 0-53 dove la settimana 0 sara'
nei giorni che intercorrono dal giorno 1 Gennaio alla prima ricorrenza della
domenica o lunedi' (dipende dalla scelta 0/1). YEARWEEK() invece rende anno
e n. settimana in forma numerica. Il range delle settimane e' 1-52.
Vediamo alcuni confronti: Il giorno 2000-01-01 era un sabato.

select week("2000-01-01") => 0 -> settimana 0 (sabato)
select week("2000-01-02") => 1 -> settimana 1 (domenica)
select week("2000-01-02","1") => 0 -> [i]settimana 0 (domenica)
select week("2000-01-03","1") => 1 -> settimana 1 (lunedi')

select yearweek("2000-01-01") => 199952 -> Anno 1999 settimana 52 (sabato)
select yearweek("2000-01-02") => 200001 -> Anno 2000 settimana 01 (domenica)
select yearweek("2000-01-02","1") => 199952 -> Anno 1999 settimana 52 (domenica)
select yearweek("2000-01-03","1") => 200001 -> Anno 2000 settimana 01 (lunedi')

Si pone l'accento su queste funzioni perche' il numero della settimana e' molto
usato nelle applicazioni aziendali (statistiche, pert, contabilita'...). Le agende in
circolazione inoltre non rispondono ad un unico standard. Sicuramente la funzione
YEARWEEK() non lascia adito a dubbi (no 0 - no 53).


MONTHNAME - DAYNAME - Queste due funzioni estraggono i nomi del mese e del
giorno da una data. Peccato siano in inglese. Si puo' facilmente convertire in
italiano con una breve funzione PHP che vedremo in seguito:

SELECT MONTHNAME(NOW()) as mese => May
SELECT DAYNAME("2003-05-20") as giorno => Tuesday


3) Estrazione di Ore, Minuti, Secondi.

HOUR(time) - MINUTE(time) - SECOND(time) - Queste funzioni estraggono ore,
minuti, secondi a partire da un dato che abbia nel contenuto ore, minuti secondi.
Puo' essere quindi un campo o funzione con dati tipo TIMESTAMP o DATETIME o TIME.
Ovviamente non potra' essere un campo con dati in formato YEAR o DATE.

SELECT HOUR(CURTIME()) as hour, MINUTE(CURTIME()) as min, SECOND(CURTIME()) as sec;
ed ecco l'equivalente di una funzione EXPLODE() con ora, minuti e secondi.


Pag 2 - SEGUE ...

Bibliografia:
http://www.mysql.com/doc/en/index.html