2013-08-16 6 views
1

J'essaie de suivre un exemple similaire d'obtenir des totaux hebdomadaires et mensuels de: StackOverFlow: SQL Add Sum Row for Week and At the End Add the Grand Total. Ce niveau de SQL est un étirement pour moi, alors soyez le plus clair possible.SQL Ajouter des totaux hebdomadaires et mensuels

J'ai une table avec plus de 200K enregistrements de ID, Store_ID, Sales_Date, montant.

ID Store_ID Amount Sales_Date 
1 215   7 1/29/2012 
2 215   7 1/30/2012 
3 215   7 1/31/2012 
4 215   7 2/1/2012 
5 215   7 2/2/2012 
6 215   7 2/3/2012 
7 215   7 2/4/2012 
8 215   8 2/5/2012 
9 215   8 2/6/2012 
10 215   8 2/7/2012 
    ***More and More Data***   
162 218   4 10/30/2011 
163 218   4 10/31/2011 
164 218   4 11/1/2011 
165 218   4 11/2/2011 
166 218   4 11/3/2011 
167 218   4 11/4/2011 
168 218   4 11/5/2011 
169 218   8 11/6/2011 
170 218   8 11/7/2011 
171 218   8 11/8/2011 
      ******LOTS MORE DATA***** 

J'ai besoin de générer une vue qui montrera les totaux hebdomadaires et mensuels pour chaque et la date Numéro magasin associé du total. Le problème que j'ai est que l'exemple me fournit des totaux hebdomadaires (sans dates associées), des totaux mensuels (sans dates associées) et les montants quotidiens (qui sont des avantages secondaires).

Je dois savoir comment ajouter dans une colonne supplémentaire les résultats qui me montreront la date de fin de la semaine et la date de fin du mois.

C'est ce que j'ai jusqu'à présent (il est presque exactement comme l'exemple):

set datefirst 7 

select top 100 
    case 
     when grouping(cast(datepart(week, [Sales_Date]) as varchar(255)))=1 then '<MonthEnd>' 
     when grouping(cast([Sales_Date] as date))=1 then '<weektotal>' 
     else cast(cast([Sales_Date] as date) as varchar(255)) 
    end as Period 
    , WkSales = sum(Amount) 
    , Store = Store_ID 
From KF_Store_Sales_Daily 

group by 
    grouping sets( 
    (cast(datepart(month, [Sales_Date]) as varchar(255)), cast(datepart(week, [Sales_Date]) as varchar(255)),cast([Sales_Date] as date)), 
    (cast(datepart(month, [Sales_Date]) as varchar(255)), cast(datepart(week, [Sales_Date]) as varchar(255))), 
    (cast(datepart(month, [Sales_Date]) as varchar(255))) 
    ) 
    , Store_ID 
ORDER BY Store_ID, Sales_Date  

Répondre

2

La requête suivante peut être utilisée pour montrer tous les jours, toutes les semaines, les totaux mensuels et annuels:

select 
    case 
     when grouping(d.m)=1 then 'Year ' + cast(max(d.y) as varchar(10)) 
     when grouping(d.w)=1 then datename(m, max(Sales_Date)) + ' ' + cast(max(d.y) as varchar(10)) 
     when grouping(Sales_Date)=1 then 'Week ' + datename(m, max(ws)) + ' ' + cast(datepart(d, max(ws)) as varchar(20)) + ' - ' 
      + datename(m, max(we)) + ' ' + cast(datepart(d, max(we)) as varchar(20)) 
     else cast(cast([Sales_Date] as date) as varchar(255)) 
    end as Period 
    , Sales = sum(Amount) 
    , Store = Store_ID 
from KF_Store_Sales_Daily 
    cross apply (
     select -- aux. expressions for dates 
      datepart(yy, [Sales_Date]), -- year 
      datepart(m, [Sales_Date]), -- month 
      datepart(wk, [Sales_Date]), -- week 
      dateadd(d, 1-datepart(w, Sales_date), Sales_date), -- week start 
      dateadd(d, 7-datepart(w, Sales_date), Sales_date) -- week end 
    ) d(y, m, w, ws, we) 
group by Store_ID, d.y, rollup (d.m, d.w, Sales_Date) 
order by d.y desc, 
    grouping(d.m), d.m, 
    grouping(d.w), d.w, 
    grouping(Sales_Date), Sales_Date 

Je ne sais pas si c'est pratique d'avoir des totaux mensuels et mensuels ensemble (puisque la semaine peut appartenir à deux mois). Après deux requêtes pour le cas si vous en aurez besoin séparément.

Pour tous les jours, les totaux mensuels et annuels:

select 
    case 
     when grouping(d.m)=1 then 'Year ' + cast(max(d.y) as varchar(10)) 
     when grouping(Sales_Date)=1 then datename(m, max(Sales_Date)) + ' ' + cast(max(d.y) as varchar(10)) 
     else cast(cast([Sales_Date] as date) as varchar(255)) 
    end as Period 
    , Sales = sum(Amount) 
    , Store = Store_ID 
from KF_Store_Sales_Daily 
    cross apply (
     select 
      datepart(yy, [Sales_Date]), 
      datepart(m, [Sales_Date]) 
    ) d(y, m) 
group by Store_ID, d.y, rollup (d.m, Sales_Date) 
order by d.y desc, 
    grouping(d.m), d.m, 
    grouping(Sales_Date), Sales_Date 

Pour tous les jours, les totaux hebdomadaires et annuels (dans ce cas, une semaine peut appartenir à deux ans):

select 
    case 
     when grouping(d.w)=1 then 'Year ' + cast(max(d.y) as varchar(10)) 
     when grouping(Sales_Date)=1 then 'Week ' + datename(m, max(ws)) + ' ' + cast(datepart(d, max(ws)) as varchar(20)) + ' - ' 
      + datename(m, max(we)) + ' ' + cast(datepart(d, max(we)) as varchar(20)) 
     else cast(cast([Sales_Date] as date) as varchar(255)) 
    end as Period 
    , Sales = sum(Amount) 
    , Store = Store_ID 
from KF_Store_Sales_Daily 
    cross apply (
     select 
      datepart(yy, [Sales_Date]), 
      datepart(wk, [Sales_Date]), 
      dateadd(d, 1-datepart(w, Sales_date), Sales_date), 
      dateadd(d, 7-datepart(w, Sales_date), Sales_date) 
    ) d(y, w, ws, we) 
group by Store_ID, d.y, rollup (d.w, Sales_Date) 
order by d.y desc, 
    grouping(d.w), d.w, 
    grouping(Sales_Date), Sales_Date 
+0

On dirait que je dois revoir Cross Apply et RollUP, mais la répartition est plus que ce à quoi je m'attendais. Je commence à penser que je dois trouver une meilleure façon d'obtenir ce dont j'ai besoin. J'essaye de recréer un rapport d'Excel qui lie à ces nombres hebdomadaires/annuels (basés sur une formule de correspondance d'index) par l'intermédiaire d'un autre Excel qui contient les données quotidiennes. Si j'utilisais cette information, je pourrais peut-être créer un déclencheur/une fonction qui se chargerait chaque semaine/chaque année dans d'autres tables. Je pense que cela permettrait également d'accélérer les rapports. Des avis? –

+0

Juste fait un peu de maths. Semble que la somme ne fait que du lundi au samedi, à l'exclusion du dimanche. Genre comme il a perdu un jour (ce dont je doute) ou utilise du lundi au dimanche comme une semaine définie. Comment pourrais-je changer cela pour être une semaine du dimanche au samedi? –

+0

@BillMannion, je pense qu'il peut résumer moins de jours pour une semaine, quand il devrait faire le total pour un mois (ou un an), et ce mois (ou l'année) se termine avant la fin de la semaine. S'il vous plaît voir l'échantillon raccourci comme SQLFiddle ([link] (http://sqlfiddle.com/#!3/0e86c/3)), il somme 7 jours pour les deux cas lorsque le début de la semaine est lundi ou dimanche, donc semble que la logique de calcul est correct. Si quelque chose n'est pas comme prévu, s'il vous plaît ajouter le résultat réel et désiré à votre question. –

Questions connexes