Strutturare una query per ricavare dei totali per ogni mese dell'anno

sabato 21 marzo 2015 - 12.44
Tag Elenco Tags  VB.NET

trinity Profilo | Guru

Buongiorno

ho questa tabella:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

ogni arrivo (data) e partenza equivale ad un numero fisico di persone arrivate o partite.
Io devo creare una query che mi dia per tutti i mesi i totale di arrivi e di partenze

esempio:

gennaio 10 5
febbraio 15 10
marzo 0 10

e così via...

In maniera frettolosa avevo pensato ad una cosa del genere:

Select 'GENNAIO' as mese, count(arrivo) as arrivi, count(partenza) as partenza from Tab_movimenti where month(arrivo)=1 union Select 'FEBBRAIO' as mese, count(arrivo) as arrivi, count(partenza) as partenza from Tab_movimenti where month(arrivo)=2 union Select 'MARZO' as mese, count(arrivo) as arrivi, count(partenza) as partenza from Tab_movimenti where month(arrivo)=3


ma ovviamente penso che ci sia di meglio. Potete darmi un'idea?

Grazie ciao

Cirillo Fabio
www.trycontact.com
www.wondernet.biz
fabio@wondernet.biz
http://blogs.dotnethell.it/fabiocirillo/
http://wnetsoftware.blogspot.com

renarig Profilo | Expert

Non mi è molto chiaro:
Nella tabella che proponi non vedo 2 campi Data ( arrivo e partenza )
ma non vedo il campo numero ( quante persone arrivano o partono )
pertanto suppongo che ogni record corrisponda sempre a solo 1 persona.



altro dubbio:
Nel caso di arrivo in Gennaio e partenza in Febbraio
dalla vista che proponi sembrerebbe che anche la
partenza venga sommata a quelle di Gennaio ???
è corretto ?????


In linea di massima io eviterei la UNION che potrebbe
anche essere valida nell'ambito di uno stesso anno,
Ma crolla se lavori con più anni,
Ti metterebbe nello stesso pentolone il Febbraio2014 con il Febbraio2015



a parer mio una base di partenza potrebbe essere questa
SELECT CAST(YEAR(arrivo) AS nvarchar) + N'/' + format(MONTH(arrivo), N'00') AS AnnoMese, COUNT(arrivo) AS Arrix, COUNT(partenza) AS Partx FROM dbo.Tab_movimenti GROUP BY CAST(YEAR(arrivo) AS nvarchar) + N'/' + format(MONTH(arrivo), N'00')
dove generiamo un codice che contiene l'Anno e il Mese
poi raggruppiamo su quel codice
e contiamo i record

Facci sapere

alx_81 Profilo | Guru

>Ti metterebbe nello stesso pentolone il Febbraio2014 con il Febbraio2015
esatto, questo è il problema anche a mio avviso più grande.
Come dice renarig, non è molto chiaro il requisito di business..
Detto questo, aggiungendo un po' di info, e comprendendo i problemi indicati, ho fatto al volo un esempio qui:
http://sqlfiddle.com/#!6/4cb0e/16

A differenza di renarig, ho preferito evitare ogni concatenazione di stringhe. Tuttavia la sua indicazione è già corretta. Solo preferisco evitare ogni possibile problema di formato e di formattazione. Noterai che il nome del mese nella mia query è indicata col DATENAME, ma, personalmente, lascerei solo il campo Numero_Mese, e poi sarà la tua applicazione a prendere decisioni sul formato.

ciao
Alessandro Alpi | SQL Server MVP
MCP|MCITP|MCTS|MCT

http://blogs.dotnethell.it/suxstellino
http://suxstellino.wordpress.com
http://mvp.microsoft.com/en-us/mvp/Alessandro%20Alpi-4014222

renarig Profilo | Expert

>... A differenza di renarig, ho preferito evitare ogni concatenazione ......
>..... e poi sarà la tua applicazione a prendere decisioni sul formato.

Concordo,
le formattazioni è sempre meglio tenerle nella applicazione

.

trinity Profilo | Guru

Buongiorno e grazie del vostro aiuto. la ricerca verrà sempre fata per intero anno quindi non avrei problemi e nel caso invece fosse per periodo lato code behind andrei a gestire i mesi di febbraio nel caso fossero bisestili.
Utilizzando linq come programmazione io avevo anche pensato a questo e ditemi se come teoria va bene:

var anno = 2015;
var risultati = (from movimento in ctx.Movimenti
where movimento.Arrivo.Year == anno
group movimento by movimento.Arrivo.Month into mesi
select new { Mese = mesi.Key, Arrivi = mesi.Count() }).ToList();

Ogni risultato è un oggetto che possiede le proprietà Mese e Arrivi. Grazie al Count(), la somma è stata fatta lato server, quindi con questa query vai ad ottenere solo i dati aggregati che effettivamente ti interessa visualizzare.

Mi servirà comunque un ciclo da 1 a 12, per riuscire a stampare tutti i mesi. Dentro il ciclo, se il mese è presente nella lista dei risultati, stampa il valore della sua proprietà "Arrivi", altrimenti sarà 0.

Se non voglio fare un ciclo potrei crearmi un array di numeri da 1 a 12 e fare una "left join" con i risultati. Ho letto questa cosa qui: https://msdn.microsoft.com/it-it/library/bb397895.aspx

Ciao e grazie

Cirillo Fabio
www.trycontact.com
www.wondernet.biz
fabio@wondernet.biz
http://blogs.dotnethell.it/fabiocirillo/
http://wnetsoftware.blogspot.com
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2025
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5