30 novembre 2008

Analytics - n.3: un indovinello con COUNT

Anche le funzioni classiche come COUNT, SUM, AVG hanno la loro controparte analitica.

Oggi utilizziamo Oracle per risolvere un indovinello, utilizzando la versione analitica delle tradizionali funzioni di gruppo. Chi lo dice che tutte le spiegazioni devono per forza essere noiose? :-)

Due DBA si incontrano all'Oracle Openworld. Il primo viene a sapere che il secondo ha 3 figlie, quindi gli chiede la loro età. Il secondo, in vena di enigmi, dice:
"Il prodotto delle età delle mie figlie è 36."
L'altro ragiona un attimo, ma chiede più informazioni, perché il solo prodotto delle età non gli basta.
"La somma delle età delle mie figlie è uguale al numero di persone che stanno in questa stanza"
L'altro conta le persone, ci pensa, ma i dati non gli bastano ancora, e chiede maggiori indizi.
"La più grande delle mie figlie ha un criceto maculato".
L'altro raggiunge un prompt SQL e, dopo pochi minuti, ha la soluzione!

Come avrà fatto?

Domani pubblicherò la soluzione.
Mi raccomando non utilizzate Google, altrimenti non è leale (sempre che si riesca a trovare con Google).
Pubblicate le vostre soluzioni nei commenti, a condizione che utilizziate SQL e le funzioni analitiche.

6 commenti:

Winter Rose ha detto...
Questo commento è stato eliminato dall'autore.
Winter Rose ha detto...

Scusa, prima ho sbagliato a scrivere.
La soluzione dipende dal numero di persone nella stanza l'ultima frase ci dice solo che la figlia maggiore non è gemella. Dato che i fattori di 36 sono 1,2,2,3,3 se le persone ad esempio sono 13 allora l'età è 2,2,9 se sono 14 allora 1,4,9 se sono 21 allora 18,2,1 etc..
Giusto?
Ciao
Adriano

Rudy ha detto...

Non utilizzi tutti i dati a disposizione.

Cmq dovresti utilizzare SQL, perché è un esercizio divertente :-)
Ah, anche la funzione COUNT() in versione analitica.

Mauro ha detto...

Tutte le soluzioni senza funzioni analitiche ma solo sql, vale lo stesso?

with tutte_eta as ( select 1 eta from dual
union all
select 2 from dual
union all
select 3 from dual
union all
select 4 from dual
union all
select 5 from dual
union all
select 6 from dual
union all
select 7 from dual
union all
select 8 from dual
union all
select 9 from dual
union all
select 10 from dual
union all
select 11 from dual
union all
select 12 from dual
union all
select 13 from dual
union all
select 14 from dual
union all
select 15 from dual
union all
select 16 from dual
union all
select 17 from dual
union all
select 18 from dual
union all
select 19 from dual
union all
select 20 from dual
union all
select 21 from dual
union all
select 22 from dual
union all
select 23 from dual
union all
select 24 from dual
union all
select 25 from dual
union all
select 26 from dual
union all
select 27 from dual
union all
select 28 from dual
union all
select 29 from dual
union all
select 30 from dual
union all
select 31 from dual
union all
select 32 from dual
union all
select 33 from dual
union all
select 34 from dual
union all
select 35 from dual
union all
select 36 from dual )
select a.eta, b.eta, c.eta, a.eta + b.eta + c.eta somma
from tutte_eta a, tutte_eta b, tutte_eta c
where a.eta * b.eta * c.eta = 36
order by a.eta, b.eta, c.eta

Rudy ha detto...

@Mauro: sì ma è solo il primo passo: non escludi i duplicati (1,4,9 4,1,9 9,4,1 ecc.) e non dai la soluzione.

Al posto di "select... from dual" io utilizzerei un generatore di numeri meno prolisso e più facilmente riutilizzabile:
ad esempio, select rownum from all_objects where rownum <= 36

Mauro ha detto...

Ho risolto il problema dei duplicati, ma non mi viene in mente niente per usare il count

with tutte_le_eta as ( select rownum eta
from all_objects
where rownum <= 36 )
select distinct eta_1, eta_2, eta_3
from( select least( a.eta, b.eta, c.eta ) eta_1
, case when a.eta <= b.eta and b.eta <= c.eta then b.eta
when a.eta <= c.eta and c.eta <= b.eta then c.eta
when b.eta <= a.eta and a.eta <= c.eta then a.eta
when b.eta <= c.eta and c.eta <= a.eta then c.eta
when c.eta <= a.eta and a.eta <= b.eta then a.eta
when c.eta <= b.eta and b.eta <= a.eta then b.eta
end eta_2
, greatest( a.eta, b.eta, c.eta ) eta_3
from tutte_le_eta a, tutte_le_eta b, tutte_le_eta c
where a.eta * b.eta * c.eta = 36
)
order by 1,2,3;