Upload
phamtruc
View
212
Download
0
Embed Size (px)
Citation preview
Pagina 1
A. Veneziani – Analisi e svolgimento simulazione 2019 Febbraio (Informatica)
Studio del testo
Il problema indicato prospetta la completa gestione si hardware (prevalentemente riguardante Sistemi e
Reti) sia software (in gran parte riguardante Informatica) di un sistema di noleggio di biciclette.
Il sistema utilizzando moderne tecniche di identificazione , tracciamento delle presenze ed altro consentiti
da moderni dispositivi elettronici, permette di tenere sotto controllo la situazione del posizionamento delle
bici nelle varie stazioni di raccolta in modo automatico.
Come riporta il testo possiamo identificare come soggetti di interesse dell’organizzazione software del
noleggio, quelli più scontati:
a) Le biciclette, considerate singolarmente con un ben preciso id
b) Le stazioni
c) Gli utenti che noleggiano o riportano le bici
Infine ai fini di una organizzazione opportuna del DB e della registrazione di tutti gli spostamenti delle bici
stesse, di devono considerare ovviamente le singole operazioni appunto di noleggio e ritorno delle bici.
Una operazione di questo tipo è facile capire ha cinque parametri fondamentali:
1) Il momento in cui è stata effettuata (data e tempo)
2) Il tipo di operazione (noleggio o ritorno)
3) In quale stazione è avvenuta
4) Chi l’ha effettuata (ossia lo specifico utente)
5) Quale bicicletta ha coinvolto
Centrale allo schema del DB sta quindi l’entità che potremmo chiamare Operazioni e che combina le altre.
I dati strategici prima citati (momento dell’operazione (dataora) e tipo dell’operazione) contenuti in tale
entità ci permettono già di organizzare i dati di modo da rispondere a tutte le richieste poste nel testo del
compito d’esame ai punti 2, 3a e 3b, e nella seconda parte, i punti I, IIa e IIb.
Progettazione del DB – Punto 2 della traccia
Per le considerazioni prima esposte, dovremo considerare il DB costituito da almeno 4 entità le quali saranno:
Utenti
Biciclette
Stazioni
Operazioni (preposta a memorizzare le varie operazioni di noleggio e ritorno)
Gli attributi che potremo prevedere per ciascuno di esse saranno:
Entità Utenti
Nome attributo Scopo
Codice fiscale Codice fiscale dell’utente – attributo chiave
Numero carta Numero della carta di credito
Nome Nome dell’utente
Cognome Cognome dell’utente
Via Via di residenza dell’utente
NCiv Numero civico di residenza
Citta Città di residenza
Telefono Telefono dell’utente (fisso o cellulare)
Mail Indirizzo mail dell’utente
Entità Biciclette
Nome attributo Scopo
Pagina 2
Id bicicletta Identificativo della bicicletta – attributo chiave
Data inizio servizio Da di ingresso in servizio della bicicletta
Km Km complessivi percorsi dalla bici
Entità Stazioni
Nome attributo Scopo
IdStazione Codice identificativo della stazione – attributo chiave
Via Via dove è situata la stazione
NCiv Numero civico
Entità Operazioni
Nome attributo Scopo
IdOpe Codice identificativo della operazione (di noleggio o ritorno) – attributo chiave
Tipo Tipo dell’operazione (noleggio o ritorno N o R)
Momento Momento in cui avviene l’operazione considerata
Le associazioni
Le associazioni tra le entità considerate sono piuttosto intuitive da immaginare. Nel diagramma l’entità
Operazioni è centrale e collegata con le altre, in quanto nel modello supposto ogni operazione, è in relazione
con un cliente che la esegue (il cliente riporta o prende una bicicletta), con una bicicletta (dato che è essa
l’oggetto del noleggio) e con una stazione (quella ove avviene la singola operazione di noleggio o reso.
Quindi avremo tre associazioni che vanno da Operazioni a Utenti, a Biciclette e a Stazioni.
La molteplicità di tali associazioni è 1 a n, con n rivolto verso Operazioni per tutte e 3 le associazioni. Infatti
ad utente corrispondono più operazioni, ma ad una operazione un solo utente che la svolge. Ad una bicicletta
corrispondono più operazioni svolte su essa, ma una operazione coinvolgerà solo una bici, ed in una stazione
si svolgono più operazioni, ma una operazione può essere svolta in una sola stazione.
La associazioni in linea di massima possono essere considerate totali, tranne eventualmente quelle di
Bicicletta verso Operazioni (perché potrebbe trattarsi di una bicicletta appena messa in servizio) e quella di
utenti verso Operazioni (perché potrebbe essere un utente appena registrato o che per ora non ha avuto
occasione di utilizzare il servizio).
Schema delle relazioni
Utenti(CF, NCarta, Nome, Cognome, Via, NCiv, Citta, Telefono, Mail)
Biciclette(IdBicicletta, DataInServ, Km)
Stazioni(IdStazione, Via, NCiv)
Operazioni(IdOpe, Tipo, Momento, CF, IdStazione, IdBici)
Relazioni in forma tabellare
Relazione Utenti
Nome campo Tipo Ampiezza NULL Chiavi
CF CHAR(16) 16 No Primaria
NCarta CHAR(20) 20 No
Nome VARCHAR(40) 40 No
Cognome VARCHAR(40) 40 No
Via VARCHAR(40) 40 No
NCiv CHAR(6) 6 No
Pagina 3
Citta VARCHAR(50) 50 No
Telefono VARCHAR(20) 20 No
Mail VARCHAR(30) 40 No
Relazione Biciclette
Nome campo Tipo Ampiezza NULL Chiavi
IdBicicletta INT UNSIGNED No Primaria
DataInServ DATE No
Km INT UNSIGNED No
Relazione Stazioni
Nome campo Tipo Ampiezza NULL Chiavi
IdStazione INT UNSIGNED No Primaria
Via VARCHAR(40) No
NCiv VARCHAR(6) No
Relazione Operazioni
Nome campo Tipo Ampiezza NULL Chiavi
IdOpe INT UNSIGNED No Primaria
Tipo ENUM(‘N’,’R’) No
Momento DATETIME No
CF CHAR(16) Si Esterna
IdStazione INT UNSIGNED No Esterna
IdBici INT UNSIGNED No Esterna
Script SQL di creazione del DB
CREATE TABLE Utenti (
CF CHAR(16) NOT NULL PRIMARY KEY,
NCarta CHAR(20) NOT NULL,
Nome VARCHAR(40) NOT NULL,
Cognome VARCHAR(40) NOT NULL,
Via VARCHAR(50) NOT NULL,
NCiv CHAR(6) NOT NULL,
Citta VARCHAR(50) NOT NULL,
Telefono VARCHAR(20) NOT NULL,
Mail VARCHAR(30) NOT NULL );
CREATE TABLE Stazioni (
IdStazione INT UNSIGNED PRIMARY KEY,
Via VARCHAR(40) NOT NULL,
NCiv CHAR(6) NOT NULL );
CREATE TABLE Biciclette (
IdBici INT UNSIGNED PRIMARY KEY,
DataInServ DATE NOT NULL,
Km INT UNSIGNED NOT NULL );
CREATE TABLE Operazioni (
Pagina 4
IdOpe INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
Tipo ENUM('N','R') NOT NULL,
Momento DATETIME NOT NULL,
CF CHAR(16),
IdStazione INT UNSIGNED NOT NULL,
IdBici INT UNSIGNED NOT NULL,
FOREIGN KEY(CF) REFERENCES Utenti(CF),
FOREIGN KEY(IdStazione) REFERENCES Stazioni(IdStazione),
FOREIGN KEY(IdBici) REFERENCES Biciclette(IdBici) );
Diagramma UML del DB
Punto 3° della traccia
Tralasciando di indicare come generare la mappa delle stazioni in forma grafica, essa una volta creata
potrebbe agire come mappa sensibile Web. Praticamente con vari meccanismi alla fine potremo ottenere
l’id (corrispondente a quello registrato nel DB come chiave primaria della tabella stazioni), di una stazione
selezionata e poi svolgere quanto richiede il quesito, ossia capire se nella stazione vi sono biciclette disponibili
per il noleggio.
Per semplificare invece della mappa ho realizzato una pagina con un selettore a discesa elencante tutte le
varie stazioni, di cui solo una potrà essere selezionata.
La generazione della lista delle stazioni e la gestione della stessa (ricarico automatico del valore selezionato)
è riportata in grigio.
A questo punto effettueremo due ricerche in cascata:
1) Nella prima individueremo per ogni bicicletta il momento dell’ultima operazione svolta su di essa:
Pagina 5
SELECT biciclette.IdBici, MAX(Momento)
FROM operazioni, biciclette
WHERE
operazioni.IdBici = biciclette.IdBici
GROUP BY biciclette.IdBici;
2) Nella seconda, basandosi sui risultati della prima operazione (1), considereremo solo i dati
dell’ultima operazione svolta su una certa bicicletta e solo se accaduta nella stazione di interesse:
SELECT *
FROM stazioni, operazioni, biciclette
WHERE
stazioni.IdStazione = operazioni.IdStazione AND
operazioni.IdBici = biciclette.IdBici AND
biciclette.IdBici = <id della bici>
AND stazioni.IdStazione = <id della stazione>
AND Momento = <ultima operazione della bici con l'id considerato>
3) Per ogni risultato ammissibile capiremo se esso sia di tipo ‘R’ (rientro).
Effettuando un conteggio sui risultati di questa ultima condizione (3), potremo capire il numero delle
biciclette presenti nella stazione stessa (numero delle bicilette che hanno come ultima operazione un
rientro nella stazione x).
La pagina PHP che realizza questo (basandosi sul DB proposto) è:
<html>
<head>
<title>Simulazione 2019 Febbraio punto 3a</title>
</head>
<body>
<form action="pagina_3a.php" method="post">
Stazione:
<select name="stazioni">
<?php
// connessione e selezione del DB
$conn = mysqli_connect("localhost","root","")
or die("Connessione fallita.");
mysqli_select_db($conn, "simulazione_2019_feb")
or die("Db selezionato non esistente.");
// estrazione della lista delle stazioni
$rs3 = mysqli_query($conn, "SELECT * FROM Stazioni");
$riga3 = mysqli_fetch_array($rs3);
while ($riga3)
{
$sele = "";
if ($_POST)
{
if ($_POST['stazioni'] == $riga3['IdStazione'])
$sele = "selected";
else
$sele = "";
}
echo '<option value="' . $riga3['IdStazione'] . '" ' . $sele . '>' . $riga3['Via'] .
"</option>";
Pagina 6
$riga3 = mysqli_fetch_array($rs3);
}
?>
</select>
<br>
<input type="submit" value="Indica bici presenti">
</form>
<?php
if ($_POST)
{
// individua il momento in cui è avvenuta l'ultima operazione su una bici (in una certa
stazione)
// individua il momento in cui è avvenuta l'ultima operazione su una bici
$rs = mysqli_query($conn, "SELECT biciclette.IdBici, MAX(Momento) As UltimoEvento " .
"FROM operazioni, biciclette " .
"WHERE " .
"operazioni.IdBici = biciclette.IdBici " .
" GROUP BY biciclette.IdBici");
$riga = mysqli_fetch_array($rs);
$bicidisp = 0;
while ($riga)
{
$rs2 = mysqli_query($conn, "SELECT * " .
"FROM stazioni, operazioni, biciclette " .
"WHERE " .
"stazioni.IdStazione = operazioni.IdStazione AND " .
"operazioni.IdBici = biciclette.IdBici AND " .
"biciclette.IdBici = " . $riga['IdBici'] .
" AND stazioni.IdStazione = " . $_POST['stazioni']
. " AND Momento = '" . $riga['UltimoEvento'] . "'");
$riga2 = mysqli_fetch_array($rs2);
if ($riga2['Tipo'] == "R") $bicidisp++;
$riga = mysqli_fetch_array($rs);
}
echo "La stazione ha " . $bicidisp . " bici disponibili in questo momento.";
}
?>
</body>
</html>
La cui parte effettivamente operativa riguardo
al problema posto è quella evidenziata in
azzurro.
Punto 3b della traccia
Il punto 3b chiede di conoscere quali siano le
bici attualmente in uso, quale utente sia ad
usarle, e da quale stazione siano partite.
Considerando sempre il criterio dell’ultima operazione effettuata su una bici, le bici attualmente in uso sono
individuabili:
1) Individuando l’ultima operazione svolta su ogni bici
SELECT biciclette.IdBici, MAX(Momento) As UltimoEvento
Pagina 7
FROM stazioni, operazioni, biciclette
WHERE
operazioni.IdBici = biciclette.IdBici
GROUP BY biciclette.IdBici
2) Scandendo tali ultime operazioni: se essa risulti di tipo ‘N’, la bici risulta in uso (ossia in noleggio)
si va a ricavare chi l’abbia noleggiata e da quale stazione provenga
SELECT *, stazioni.Via As Via_
FROM stazioni, operazioni, biciclette, utenti
WHERE
stazioni.IdStazione = operazioni.IdStazione AND
operazioni.IdBici = biciclette.IdBici AND
operazioni.CF = utenti.CF AND
biciclette.IdBici = <id della bici considerata>
AND Momento = <ultima operazione svolta su quella bici>
In questo caso l’operazione di ricerca è del tutto generale, quindi non vi sono input per la pagina che la
effettua. Essa ricerca in generale su tutte le biciclette se l’ultima operazione sia del tipo “noleggio” e quindi
deduce che tale biciletta sia in noleggio, ricavandone utente noleggiante e stazione da cui sia stata
noleggiata.
<html>
<head>
<title>Simulazione 2019 Febbraio punto 3b</title>
</head>
<body>
<b>Elenco delle bici in uso:</b><br>
<?php
// connessione e selezione del DB
$conn = mysqli_connect("localhost","root","")
or die("Connessione fallita.");
mysqli_select_db($conn, "simulazione_2019_feb")
or die("Db selezionato non esistente.");
// individua il momento in cui è avvenuta l'ultima operazione su una bici (in una certa
stazione)
$rs = mysqli_query($conn, "SELECT biciclette.IdBici, MAX(Momento) As UltimoEvento " .
"FROM stazioni, operazioni, biciclette " .
"WHERE " .
"operazioni.IdBici = biciclette.IdBici " .
" GROUP BY biciclette.IdBici");
$riga = mysqli_fetch_array($rs);
$bici_circo = 0;
while ($riga)
{
$rs2 = mysqli_query($conn, "SELECT *, stazioni.Via As Via_ " .
"FROM stazioni, operazioni, biciclette, utenti " .
"WHERE " .
"stazioni.IdStazione = operazioni.IdStazione AND " .
"operazioni.IdBici = biciclette.IdBici AND " .
"operazioni.CF = utenti.CF AND " .
"biciclette.IdBici = " . $riga['IdBici'] .
" AND Momento = '" . $riga['UltimoEvento'] . "'");
Pagina 8
$riga2 = mysqli_fetch_array($rs2);
if ($riga2['Tipo'] == "N")
{
$bici_circo++;
echo "La bicicletta " . $riga['IdBici'] .
" è in uso a " . $riga2['Nome'] . " " . $riga2['Cognome'] .
" ed è stata prelevata dalla stazione di " . $riga2['Via_'] . "<br>";
}
$riga = mysqli_fetch_array($rs);
}
echo "Le bici circolanti sono in
numero " . $bici_circo;
?>
</body>
</html>
Svolgimento punto I della traccia
Possiamo considerare che con il disegno del DB
considerato, selezionato un certo utente e
ordinate le operazioni secondo il tempo in cui sono accadute, le operazioni dovrebbero presentarsi, in una
situazione normale, come una serie di operazioni di tipo N e poi R, su stazioni differenti o uguali.
La durata del singolo noleggio si può quindi dedurre dal tempo trascorso tra una operazione N e la operazione
subito successiva R. Questa coppia di operazioni impegnerà peraltro, ovviamente, la stessa bicicletta (quella
utilizzata per il noleggio).
Si tratta quindi di analizzare per lo specifico utente le coppie di operazioni di questo tipo e dedurne i dati
richiesti dalla traccia.
Qui riporto una soluzione relativa ad un sistema a pagine Web.
La prima pagina preparata roduce la lista degli utenti, dei quali si desidera avere il report.
Il link alla seconda pagina è integrato al passaggio verso la pagina stessa di un valore passato come parametro
sulla linea degli indirizzi:
<html>
<head>
<title>Simulazione 2019 Febbraio punto I (lista clienti)</title>
</head>
<body>
<?php
// connessione e selezione del DB
$conn = mysqli_connect("localhost","root","")
or die("Connessione fallita.");
mysqli_select_db($conn, "simulazione_2019_feb")
or die("Db selezionato non esistente.");
$rs = mysqli_query($conn, "SELECT * FROM Utenti");
?>
<table>
<tr><td><b>Codice fiscale</b></td><td><b>Nome</b></td><td><b>Cognome</b></td></tr>
<?php
$riga = mysqli_fetch_array($rs);
while ($riga)
{
Pagina 9
echo '<tr><td><a href="pagina_punto_I.php?cf=' . $riga['CF'] . '">' . $riga['CF'] .
'</a></td><td>' . $riga['Nome'] . '</td><td>' . $riga['Cognome'] . '</td></tr>';
$riga = mysqli_fetch_array($rs);
}
?>
</body>
</html>
La pagina più importante e critica tuttavia è
ovviamente quella che compone il report vero e
proprio.
Essa si compone di una query che individua tutte
le operazioni dell’utente in questione, mettendole
in più in ordine di tempo. Come già considerato,
due operazioni di noleggio e rientro per uno stesso
utente avranno la caratteristica di essere:
Contigue se i record sono ordinati
temporalmente
Avere una operazione di tipo N prima e una
operazione di tipo R a seguire
Temporalmente non ci saranno altre
operazioni interne all’intervallo per quell’utente
(l’utente ha già una bicicletta in noleggio).
La bicicletta nelle due operazioni sarà la medesima
Si noti che eventuali operazioni N o R di natura diversa (spostamenti da parte della società di gestione) sono
automaticamente escluse da questa lista in quanto con campo CF a valore NULL.
Successivamente nella scansione dei record risultanti vi possono essere 3 situazioni ammissibili (altre
combinazioni sono da escludere perché presupporebbero una incoerenza nel DB):
Il numero di record è pari e ovviamente i record di tipo N ed R delle operazioni sono correttamente
alternati temporalmente (ad esempio N -> R -> N -> R). Ci troviamo nel caso di una serie di noleggi
tutti già conclusi.
Il numero di record è dispari e pur seguendo la solita sequenza (N -> R -> N -> R -> N) la catena finisce
con un record con tipo N. Questa situazione sta ad indicare che l’utente ha un noleggio in corso.
Ultima evenienza è che l’utente non abbia ancora noleggiato nulla e quindi in operazioni non si
trovano record correlati al suo codice fiscale.
Detto questo la pagina opera:
a) Individuando il primo record N e registrando il momento di inizio del noleggio
b) Passando poi al record successivo
c) Controllando se il record successivo:
1. Non esista (allora deduco che è una operazione di noleggio in corso)
2. Esista e quindi sarà di tipo R (e quindi è una operazione di noleggio conclusa)
d) Rilevo anche in questo ultimo caso il tempo di fine noleggio (caso 2) od il tempo corrente attuale
(caso 1)
e) Effettuerò poi un delta tra i tempi da calcolare in ore
f) Dato il costo orario del noleggio (nel nostro esempio inserito nel codice della pagina) è possibile
ricavare il costo del singolo noleggio.
g) Un opportuno accumulatore permette di calcolare anche il costo totale di tutti i noleggi.
Le operazioni particolari utilizzate nella pagina sono:
Pagina 10
La generazione della data ed ora corrente tramite la funzione date(…)1
la conversione di un dato in formato data + tempo in forma di testo, da testo ad un valore intero in
secondi in PHP tramite la funzione strtotime(….)2
l’esecuzione di una operazione di differenza di tempi tramite il comune operatore di sottrazione
infine la conversione ad ore del valore differenza che è espresso ancora in secondi (tramite la
semplice considerazione che un ora è formata da 3600 secondi).
l’uso della funzione number_format(…)3 per formattare gli output double in formato con virgola fissa
a 2 decimali e la virgola come separatore
<html>
<head>
<title>Simulazione 2019 Febbraio punto I (report)</title>
</head>
<body>
<?php
define("PREZZO_ORA",0.5); // prezzo per ora implementato nel codice della pagina
// connessione e selezione del DB
$conn = mysqli_connect("localhost","root","")
or die("Connessione fallita.");
mysqli_select_db($conn, "simulazione_2019_feb")
or die("Db selezionato non esistente.");
// la query trova la sequenza di operazioni ordinata nel tempo di un
// certo utente. Le operazioni dovrebbero alternarsi con tipo
// N / R / N / R e cosi' via...
// Se l'ultima operazione è di tipo N un noleggio è ancora in corso...
$rs = mysqli_query($conn, "SELECT * " .
"FROM stazioni, operazioni, biciclette, utenti " .
"WHERE " .
"stazioni.IdStazione = operazioni.IdStazione AND " .
"operazioni.IdBici = biciclette.IdBici AND " .
"operazioni.CF = utenti.CF AND " .
"utenti.CF = '" . $_GET['cf'] . "' " .
"ORDER BY Momento");
$riga = mysqli_fetch_array($rs);
$nessuno = true;
$totale = 0;
while ($riga)
{
echo "<br><br>";
// se il record corrente e' di tipo "noleggio" (N)
if ($riga['Tipo'] == 'N')
{
// memorizza il tempo di inizio noleggio
$tinizio = $riga['Momento'];
$t1 = strtotime($tinizio);
echo "inizio noleggio il " . $tinizio . "<br>";
// passa al record successivo (immediatamente successivo) in ordine di tempo
1 http://php.net/manual/en/function.date.php 2 http://php.net/manual/en/function.strtotime.php 3 http://php.net/manual/en/function.number-format.php
Pagina 11
$riga = mysqli_fetch_array($rs);
}
// se il record successivo e' di tipo R (rientro dal noleggio)
if ($riga['Tipo'] == 'R')
{
// memorizza il tempo di fine noleggio
$tfine = $riga['Momento'];
$t2 = strtotime($tfine);
echo "fine noleggio il " . $tfine . "<br>";
}
// se il record successivo non esiste ....
if (! $riga)
{
echo "Ultimo noleggio ancora in corso...<br>";
// genera una stringa (nel formato indicato) contenente il tempo corrente
$adesso = date('Y-m-d H:i:s');
$t2 = strtotime($adesso);
}
// calcola la differenza dei tempi di noleggio (in secondi)
$diff = $t2 - $t1;
// calcolo il delta in ore e ne aggiungo una di default (la prima)
$ore_noleggio = ((int) ($diff / (60 * 60))) + 1;
echo "Ore di durata del noleggio: " . $ore_noleggio . "<br>";
$spesa = PREZZO_ORA * $ore_noleggio;
echo "Spesa per il noleggio: " . number_format($spesa,2,",",".") . "<br>";
$totale = $totale + $spesa; // calcolo con accumulo della spesa totale
$riga = mysqli_fetch_array($rs);
$nessuno = false;
}
if ($nessuno) echo "Nessun noleggio effettuato.";
echo "<br><br>Totale spesa noleggi: " .
number_format($totale,2,",",".");
?>
</body>
</html>
L’invio periodico del report presuppone un applicativo che
riesca a effettuare l’operazione in momenti determinati. Si
potrebbe ad esempio pensare ad uno script PHP (per rimanere
nell’ambito dello stesso linguaggio) di tipo console che sia
lanciato e giri sul server, e lo stesso legga ripetutamente il
tempo corrente di sistema ad intervalli di tempo laschi.
L’operazione potrebbe essere realizzata con un ritardo lungo
ed un ciclo infinito. Al momento che il valore del mese letto cambia, si dovrebbe eseguire una parte di codice
che, composto il report, generato con metodi simili a quelli applicati nelle pagine Web qui sopra, lo cumuli in
una stringa e lo immetta in una operazione di invio mail verso il relativo cliente (comando PHP mail(…)).
Il DB tra l’altro mette a disposizione anche l’indirizzo mail del cliente stesso, proprio per permettere questa
operazione in modo del tutto automatico.
In questo modo i report, ad ogni inizio mese verrebbero erogati a tutti i clienti via mail in modo
contemporaneo, tramite un ulteriore ciclo che scansisca tutti gli utenti, in rapida successione.
Pagina 12
Svolgimento punti IIa e IIb
Si tratta di due classiche query sul DB richieste per risolvere i problemi indicati:
a) Dato il codice di una bicicletta elencare gli utenti che l’hanno utilizzata nel mese corrente.
Si noti che MONTH isola in un dato datetime SQL il solo valore del mese e che il mese corrente può essere
facilmente ricavato grazie alla importante funzione NOW() che produce appunto un datetime col tempo
corrente (la query ipotizza di testare gli utilizzi della bici di id 3):
SELECT DISTINCT utenti.*
FROM biciclette, operazioni, utenti
WHERE
biciclette.IdBici = operazioni.IdBici AND
operazioni.CF = utenti.CF AND
biciclette.IdBici = 3 AND
MONTH(NOW()) = MONTH(Momento);
b) Mostrare la stazione presso la quale è stato effettuato il maggior numero di noleggi in un dato
periodo.
CREATE OR REPLACE VIEW Noleggi AS
SELECT stazioni.IdStazione, stazioni.Via, COUNT(*) AS NumNoleggi
FROM stazioni, operazioni
WHERE
stazioni.IdStazione = operazioni.IdStazione AND
operazioni.Tipo = 'N' AND
Momento BETWEEN '2019-01-01' AND '2019-12-31'
GROUP BY stazioni.IdStazione;
in questa seconda query si crea una view che individua tutti i noleggi nel periodo desiderato e li raggruppa
per stazione contando il loro numero.
Resta però da determinare su quale stazione sia stato effettuato il maggior numero di noleggi.
Questo può essere fatto utilizzando la tabella dei dati creati dalla view e cercando in essa il massimo valore
di noleggi. Successivamente sempre sulla stessa view Noleggi si andranno a selezionare solo i record (ed il
relativo dato delle stazioni) che presentano quel numero di noleggi (ossia il massimo) e non altri:
SELECT IdStazione, Via, NumNoleggi
FROM Noleggi
WHERE NumNoleggi =
(SELECT MAX(NumNoleggi)
FROM Noleggi);