1

我正在根据给定的月份/年份选择列的计数。与上个月相比,我需要返回该计数的百分比差异。

这是我到目前为止所拥有的。这将返回我需要的前半部分(当前月份计数)。

select 
    o.productName, COUNT(*) as totalSales 
from 
    order o
inner join 
    product p on o.productID=p.productID
where 
    datePart(month, dateTimeReceived) = 2
    and datePart(year, dateTimeReceived) = 2012         
group by 
    o.productName
order by 
    totalSales desc

所以这个的输出如下

Widget 1  - 200 sold
Widget 2  - 190 sold

同样,我还想包含第三列,它记录了上个月的百分比变化。

此外,关于我如何选择,我并没有感到温暖的模糊,datePart所以如果你有关于如何更好地接近它的建议,我将不胜感激!

4

2 回答 2

2

有多种方法可以产生您想要的结果。这个使用 CTE 计算两个月的总数,然后将其连接回自身。

With cte as 
(
SELECT 

       o.productname, 
       Datepart(month, datetimereceived) m,
       Count(*) AS totalSales 
FROM   order o 
       INNER JOIN product p 
               ON o.productid = p.productid 
WHERE  Datepart(month, datetimereceived) in ( 2, 2-1) 
       AND Datepart(year, datetimereceived) = 2012 
GROUP  BY o.productname, 
       Datepart(month, datetimereceived) 
ORDER  BY totalsales DESC )
SELECT 
      a.productName ,
      a.totalSales,
      a.totalSales / b.totalSales percentage_of_prevous_month

FROM 
      cte a 
      INNER JOIN cte b 
      ON a.productname = b.productname
         and a.month = b.month - 1

There are some pieces missing. You'll probably actually need to do something like to get a non zero value, if the division results in a number < 0

cast(a.totalSales as decimal)/ cast( b.totalSales  as decimal) 

Also the using the Month input like this will cause problems if your input is January. So you're better of normalizing the datetimerecived to the first of the month

e.g.

Modified SELECT and Group by

   CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(@mydate)-1),datetimerecieved),101) m

Modified WHERE

   CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(datetimerecieved)-1),datetimerecieved),101)
                  in ( '2/1/2012', DateAdd(m,-1,'2/1/2012'))

Modified ON

a.M > b.M
于 2012-06-26T05:26:32.177 回答
1

EDITED: Didn't read the bit about the percentage column. This returns 4 columns, productName, currentMonth, previousMonth and percentChange. The ISNULL function is there to prevent "divide by zero" errors. You could adapt this into a proc and just pass in the CurrentYear & CurrentMonth parameters, or you could pass in a single datetime parameter and let it work out the month/year from that, or even use GETDATE() and not pass any parameters.

declare @CurrentYear int,
    @CurrentMonth int,
    @previousYear int,
    @previousMonth int

set @CurrentYear = 2012
set @CurrentMonth = 2

if @CurrentMonth = 1 begin
    set @previousMonth = 12
    set @previousYear = @CurrentYear - 1
end else begin
    set @previousMonth = @CurrentMonth - 1
    set @previousYear = @CurrentYear
end

select  productName,
    (select COUNT(*) 
    from    [order] o 
    where   DATEPART(year, dateTimeReceived) = @CurrentYear
    and DATEPART(month, dateTimeReceived) = @CurrentMonth
    and o.productid = p.productid) as currentMonth,
    (select COUNT(*) 
    from    [order] o 
    where   DATEPART(year, dateTimeReceived) = @previousYear
    and DATEPART(month, dateTimeReceived) = @previousMonth
    and o.productid = p.productid) as previousMonth,
    convert(decimal(10, 2), 100*(
    (select COUNT(*) 
    from    [order] o 
    where   DATEPART(year, dateTimeReceived) = @CurrentYear
    and DATEPART(month, dateTimeReceived) = @CurrentMonth
    and o.productid = p.productid) 
    -
    (select COUNT(*) 
    from    [order] o 
    where   DATEPART(year, dateTimeReceived) = @previousYear
    and DATEPART(month, dateTimeReceived) = @previousMonth
    and o.productid = p.productid)
    /
    NULLIF(
    (select COUNT(*) 
    from    [order] o 
    where   DATEPART(year, dateTimeReceived) = @previousYear
    and DATEPART(month, dateTimeReceived) = @previousMonth
    and o.productid = p.productid), 0))) as percentChange
from    product p
于 2012-06-26T09:20:24.203 回答