Newsgroup: it.comp.software.database
Titolo: Un caso interessante

Uso mysql.
Tabella "nascite" che registra i nati in un determinato posto, con i
seguenti dati:
- id (PK)
- giorno
- mese
- anno
- nome
eccetera.
Voglio fare una statistica sulle natalità nei vari mesi, che mi produca un
recordset di questo tipo:
+----+---------+---------+---------+
|mese|1600-1650|1651-1700|1701-1750|
+----+---------+---------+---------+
|gen |       10|       12|        8|
|feb |       15|       10|       12|
|mar |       20|       21|       26|
|apr |       30|       28|       25|
|mag |   . . . . . [eccetera]      |
+----+---------+---------+---------+
cioè in sostanza voglio sapere, per gruppi di 50 anni, quanti nascono in
ogni mese.
L'istruzione base vabbé, è:
SELECT mese, COUNT(mese) AS '1600-1650' FROM nascite
WHERE anno BETWEEN 1600 AND 1650;
ma così ottengo solo un cinquantennio alla volta.
Come faccio a crearmi una colonna per ogni gruppo di anni?
Suppongo che su un altro dbms si potrebbero usare subqueries tipo
SELECT mese,
    (SELECT COUNT(mese) AS '1600-1650' FROM nascite WHERE anno BETWEEN 1600
AND 1650 group by mese),
    (SELECT COUNT(mese) AS '1651-1700' FROM nascite WHERE anno BETWEEN 1651
AND 1700 group by mese),
[eccetera... per ogni cinquantennio ]
FROM nascite GROUP BY mese;
Ma
1. non so se in assoluto è corretta (certamente no! Infatti grazie a mysql
mai usate subqueries!)
2. come faccio in mysql che non supporta le subqueries?
Magari il mio approccio è totalmente sbagliato. Pendo dalle vostre tastiere.

 wrote in
news:9ulb07$6a8$
1...@newsfeed.cineca.it
: 

prova così:
select mese,
case anno
when anno between 1800 and 1849 then '1800-1849'
when anno between 1850 and 1899 then '1850-1899'
when anno between 1900 and 1949 then '1900-1949'
when anno between 1950 and 1999 then '1950-1999'
when anno between 2000 and 2049 then '2000-2049'
else 'passato remoto' end, count(*) group by 2;
(non sono sicurissimo, non ho le tue tabelle sotto mano!)
ciao

 wrote in 
news:Xns916EAE3EEB...@10.16.96.46
:

ah, fammi sapere se funziona...

Grazie, Punkarruso, sto cercando documentazione sui case e sto facendo varie
prove...
Ma sono riuscito a fare solo qualcosa tipo:
select cognome,
case nome
   when nome like '%o' then 'uomo'
   when nome like '%a' then donna'
   else 'non so' end
as 'sesso'
from persone;
per ottenere una cosa tipo:
+----------+--------+
| cognome  | sesso  |
+----------+--------+
| De André | uomo   |
| Prati    | donna  |
| Prati    | donna  |
| Bush     | non so |
+----------+--------+
Peraltro la cosa curiosa è che neanche questo va via liscio!! Mi dà uomo per
tutti i nomi femminili e donna per tutti quelli maschili! :( ?!?! E non mi
dà mai 'non so'.
Ma, come dicevo, non conosco bene questa funzione, probabilmente devo capire
con che ordine valuta i case; la documentazione di MySQL però non dà
indicazioni in merito.
Continuerò coi tentativi.
Tuttavia non mi risolve esattamente quello che cercavo...
Io volevo creare delle colonne fittizie, in cui, in ogni colonna, sommasse
dei dati rispondenti a determinati criteri (intervalli di tempo), tipo:
+----+---------+---------+---------+
|mese|nati 1700|nati 1800|nati 1900|
+----+---------+---------+---------+
|gen |      100|      120|      130|
|feb |      150|      188|      100|
|mar |      200|      180|      201|
+----+---------+---------+---------+
~ Lampo di genio!!! ~
Forse devo usare degli alias, tipo:
SELECT 1700.qualcosa, 1800.qualcosa, 1900.qualcosa
FROM nati AS 1700, nati AS 1800, nati AS 1900
WHERE 1700.nati BETWEEN 1701 AND 1800
  AND 1800.nati BETWEEN 1801 AND 1900
  AND 1900.nati BETWEEN 1901 AND 2000
GROUP BY ...
Fico! Che genio! WOW!! Adesso provo! Mi sento come folgorato sulla via di
Damasco.
Ah, vivo per queste emozioni!!
(Per la verità io sto lavorando sui dati di un registro dei morti, ma
l'esempio mi sembrava troppo macabro!!)

 GROUP BY ...
suppongo che così ti venga un gigantesco merge delle 3 tabelle 1700 1800
e 1900... ... o sbaglio??
purtroppo a me non vengono in mente altri modi al di fuori di quello che
ti ho detto io. chiaramente, così avresti:
 (se ci metti anche order by)
1800-1849    	gennaio    	162
1800-1849    	febbraio    	180
...
ecc..
non proprio quello che volevi tu ma con un po' di fantasia puoi gestire 
questi dati come gli altri, essendo gli stessi per contenuto anche se 
diversi per forma.
ciao

 e 1900... ... o sbaglio??
Beh, ovviamente bisogna mettere i vari vincoli tipo and 
1700.id
 = 
1800.id
eccetera
Il problema č che non funziona... Ci sto ancora lavorando, ma sono quasi
sicuro che con una subquery la cosa sarebbe fattibile.
Resta il limite di MySQL per le subqueries.
Resto in attesa di altri suggerimenti.

 Resto in attesa di altri suggerimenti.
un altro suggerimento potrebbe essere che magari fare delle subquery e 
delle join della madonna risulterebbe più lento e dispendioso che non fare 
delle piccole query mirate...

 delle piccole query mirate...
Sì, posso estrarmi un recordset per ogni periodo, e poi unire il tutto
(oltretutto, se uno usa un'interfaccia tipo PHP può gestirsi l'output con
molta libertà). Comunque, a un livello squisitamente dottrinale, mi resta la
curiosità: si potrà ben fare... E come?
Comunque ti ringrazio veramente per i suggerimenti.

 resta la curiosità: si potrà ben fare... E come?
con le subqueries!!
se ti può interessare, dalla release 4.1 MySQL supporterà le nested 
queries... questo fa ben sperare anche per la futura implementazione delle 
viste!!
ciao

Ci sono riuscito, grazie a un aiuto, da solo non ce l'avrei fatta! E come
sempre accade in questi casi la soluzione sembra elementare!
La strada era quella che avevi suggerito all'inizio, punkarruso: usare i
case. Ecco, nel caso servisse a qualcun altro, la soluzione.
select mese,
sum(case when anno between 1601 and 1700 then 1 else 0 end) as "XVII sec",
sum(case when anno between 1701 and 1800 then 1 else 0 end) as "XVIII sec"
from nascite
group by mese order by mese;
Oppure:
select mese,
sum(if(anno between 1601 and 1700, 1, 0)) as "XVII sec",
sum(if(anno between 1701 and 1800, 1, 0)) as "XVIII sec"
from nascite
group by mese order by mese;
Saluti a tutti e grazie

 group by mese order by mese;
complimenti!! ottima didattica! (anche la scansione della tabella non č 
elevata come una join).
io avrei usato il work-around che ti avevo consigliato.
che mi serva da lezione!!
ciao