2009-06-26 5 views
0

Pour l'amour de simplicités, je vais faire un exemple similaire à ce que j'ai:SQL: Comment Groupe par Custom Année

Disons un db a une table de commandes avec un champ de OrderDate et un champ Société. Ensuite, il y a un tableau des sociétés et chaque enregistrement a un YearEndingDate (qui signifie que l'année se termine à cette date chaque année, par exemple 6/6).

Je dois additionner toutes les commandes pour chaque année.

Je suppose que ce devrait être quelque chose comme ce chiffre, mais je ne peux pas tout à fait dehors:

SELECT SUM(orderValue), 
CASE WHEN orderDate <= YearEndingDate THEN DatePart(year, orderDate) 
CASE WHEN orderDate > YearEndingDate THEN DatePart(year, orderDate) + 1 
END as Year 
FROM Orders 
INNER JOIN Company ON Company.companyID = Order.companyID 
GROUP By Company, Year 

Toutes les idées?

+1

Vous devez spécifier quel SGBD que vous utilisez. – ahsteele

+0

Je laissais intentionnellement cela parce que je dois le faire dans un SQLite local db et un serveur central SqlServer – Jared

Répondre

1

Vous ne savez pas quel RDMS vous utilisez mais cela devrait faire l'affaire. Les trucs datepart et dateadd sont spécifiques à tsql mais je suppose que vous auriez accès à des fonctions similaires sur n'importe quelle plate-forme que vous utilisez. Le cas dans l'où détermine la valeur de l'année à utiliser.

Réponse:

select c.companyid 
     ,yearendingdate + '/' + convert(varchar, datepart(yy, dateadd(yy,1,o.orderdate))) as yearending 
     ,sum(ordervalue) as numberoforders 
    from @orders o 
     join @companies c 
     on o.companyid = c.companyid 
where orderdate between case when (cast(yearendingdate + '/' + convert(varchar, datepart(yy, o.orderdate)) as datetime) >= o.orderdate) 
         then yearendingdate + '/' + convert(varchar, datepart(yy, dateadd(yy,-1,o.orderdate))) 
         else yearendingdate + '/' + convert(varchar, datepart(yy, o.orderdate)) 
          end 
        and 
         case when (cast(yearendingdate + '/' + convert(varchar, datepart(yy, o.orderdate)) as datetime) >= o.orderdate) 
         then yearendingdate + '/' + convert(varchar, datepart(yy, o.orderdate)) 
         else yearendingdate + '/' + convert(varchar, datepart(yy, dateadd(yy,1,o.orderdate))) 
          end 
group by c.companyid, o.orderdate, yearendingdate 

Code pour comprendre problème:

declare @orders table (OrderDate datetime 
         ,CompanyID varchar(20) 
         ,OrderValue int) 

insert into @orders 
values (getdate(),'MS',2) 

insert into @orders 
values (DateAdd(year, -1, getdate()),'MS',3) 

insert into @orders 
values (DateAdd(year, -1, getdate()),'MS',1) 

insert into @orders 
values (DateAdd(year, 1, getdate()),'MS',4) 

insert into @orders 
values (DateAdd(year, 1, getdate()),'Blizzard',2) 

insert into @orders 
values (getdate(),'MS',11) 

declare @companies table (CompanyID varchar(20) 
         ,YearEndingDate varchar(20)) 

insert into @companies 
values ('MS', '05/6') 

insert into @companies 
values ('Blizzard', '07/01') 

select c.companyid 
     ,o.orderdate 
     ,yearendingdate + '/' + convert(varchar, datepart(yy, o.orderdate)) as sameyear 
     ,yearendingdate + '/' + convert(varchar, datepart(yy, dateadd(yy,1,o.orderdate))) as plusyear 
     ,yearendingdate + '/' + convert(varchar, datepart(yy, dateadd(yy,-1,o.orderdate))) as minusyear 
    from @orders o 
     join @companies c 
     on o.companyid = c.companyid 

select c.companyid 
     ,yearendingdate + '/' + convert(varchar, datepart(yy, dateadd(yy,1,o.orderdate))) as yearending 
     ,sum(ordervalue) as numberoforders 
    from @orders o 
     join @companies c 
     on o.companyid = c.companyid 
where orderdate between case when (cast(yearendingdate + '/' + convert(varchar, datepart(yy, o.orderdate)) as datetime) >= o.orderdate) 
         then yearendingdate + '/' + convert(varchar, datepart(yy, dateadd(yy,-1,o.orderdate))) 
         else yearendingdate + '/' + convert(varchar, datepart(yy, o.orderdate)) 
          end 
        and 
         case when (cast(yearendingdate + '/' + convert(varchar, datepart(yy, o.orderdate)) as datetime) >= o.orderdate) 
         then yearendingdate + '/' + convert(varchar, datepart(yy, o.orderdate)) 
         else yearendingdate + '/' + convert(varchar, datepart(yy, dateadd(yy,1,o.orderdate))) 
          end 
group by c.companyid, o.orderdate, yearendingdate 
+0

Il y a plusieurs itérations de cette réponse parce que je me suis éloigné pendant une heure et j'ai réalisé que j'avais un problème où orderdates existant avant une date de fin d'année aurait été expulsée. J'ai ajouté l'énoncé de cas pour tenir compte de cette question. Enfin, les variables de table sont là pour que je puisse tester la solution. – ahsteele