需要有关SQL聚合查询的帮助

时间:2009-12-21 21:18:50

标签: sql sql-server sql-server-2005 data-warehouse

生成可在SQL Server Reporting Services报告中使用的数据集的最直接方法是什么,以显示以下内容:

SalesPerson        # Sales        # Gross        Profit
John Doe               100       $140,000       $25,000
Everyone Else (Avg.)  1200     $2,000,000      $250,000


Jane Smith              80       $100,000       $15,000
Everyone Else (Avg.)  1220     $2,040,000      $260,000


...and so on.

这是我正在尝试做的一个非常非常简化的例子(例如,真实场景涉及将'Everyone Else'分为三个分类行),但它说明了显示聚合的主要目标每个人的数据与其他人比较(独家)。伪代码会好的。我对SQL代码的第一次尝试非常迅速,我知道必须有一个更直接的方法。

任何提示赞赏。

4 个答案:

答案 0 :(得分:1)

如果你不介意以后格式化,那么如果我们假设你有类似的东西:

sales_model_02

首先,我需要一些辅助变量来计算总数

/* Few helper variables*/
DECLARE @TotalQuantity int
       ,@TotalAmount decimal(19, 4)
       ,@TotalProfit decimal(19, 4)
       ,@EveryoneElse int

然后我们获取给定时期内每个人的总数(YEAR = 2009)

/* Fetch totals in the period*/
SELECT  @TotalQuantity = sum(SalesQuantity)
       ,@TotalAmount = sum(SalesAmount)
       ,@TotalProfit = sum(Profit)
       ,@EveryoneElse = count(DISTINCT SalesPersonKey) - 1
FROM   factSales AS s
       JOIN dimDate AS d ON s.DateKey = d.DateKey
WHERE   [Year] = 2009

/* Now we have totals for everyone in the period */

现在,对于每个人与其他人,但都在一排。

/* Totals for each sales person vs everyone else Average */
SELECT  FullName
       ,SUM(SalesQuantity) AS [PersonSalesCount]
       ,SUM(SalesAmount) AS [PersonSalesAmount]
       ,SUM(Profit) AS [PersonSalesProfit]
       ,( @TotalQuantity - SUM(SalesQuantity) ) / @EveryoneElse AS [EveryoneElseAvgSalesCount]
       ,( @TotalAmount - SUM(SalesAmount) ) / @EveryoneElse AS [EveryoneElseAvgSalesAmount]
       ,( @TotalProfit - SUM(Profit) ) / @EveryoneElse AS [EveryoneElseAvgSalesProfit]
FROM    factSales AS s
        JOIN dimDate AS d ON s.DateKey = d.DateKey
        RIGHT JOIN dimSalesPerson AS p ON p.SalesPersonKey = s.SalesPersonKey
WHERE   [Year] = 2009
GROUP BY FullName

现在,您可以将所有这些打包在包含日期间隔参数的存储过程中。可能仍需要调整销售人员的数量,以确定在一定时期内哪些活跃,以及如何计算那些没有销售任何东西的人。有了这个,EveryoneElse意味着卖东西的销售人数-1;所以,如果你有10个销售人员,只有5个销售的东西,而不是EveryoneElse = 4

答案 1 :(得分:0)

几乎肯定不是非常高效,但声明清楚:

declare @i int = 0
declare @j int = 1

select * from
(
select (@i = @i + 2) as order_col, SalesPerson, sales, gross, profit
from myTable order by SalesPerson

union all

select (@j = @j + 2) as order_col, 'Everybody else'
, (select sum(sales) from myTable i where i.SalesPerson <> o.Salesperson)
, (select sum(gross) from myTable i where i.SalesPerson <> o.Salesperson)
, (select sum(profit) from myTable i where i.SalesPerson <> o.Salesperson)
from myTable o
order by SalesPerson
) x order by order_col

UNION的第二部分肯定可以改进,但已经很晚了,我不能直接思考..)

答案 2 :(得分:0)

在SSRS中,在表格中添加一个额外的细节行。然后在聚合函数上使用Scope参数,并根据第一原则进行平均。

例如:

(Sum(Fields!Sales.Value, "table1") - Fields!Sales.Value) 
/
(Sum(Fields!NumSales.Value, "table1") - Fields!NumSales.Value)

答案 3 :(得分:0)

我在这里做了一些假设,但如果你有一个像这样的表

If object_id('Sales') is not null 
  Drop table Sales

CREATE TABLE [dbo].[Sales]
(
 [Salesperson] [nvarchar](50) NULL,
 [Sales] [int] NULL,
 [Gross] [money] NULL,
 [Profit] [money] NULL,
)

这样填充了数据

Insert into Sales values ('John Doe', 100, 200.00, 100.00)
Insert into Sales values ('John Doe', 125, 300.00, 100.00)
Insert into Sales values ('Jane Smith', 100, 200.00, 100.00)
Insert into Sales values ('Jane Smith', 125, 1.00, 0.50)
Insert into Sales values ('Joel Spolsky', 100, 2.00, 1.00)
Insert into Sales values ('Joel Spolsky', 125, 3.00, 1.00)

然后像这样的存储过程可能会给你你想要的东西

If object_id('usp_SalesReport') is not null 
Drop procedure usp_SalesReport

Go


Create Procedure usp_SalesReport
as
Declare @results as table
(
 SalesPerson nvarchar(50),
 Sales int,
 Gross money,
 Profit money
)

Declare  @SalesPerson nvarchar(50)
Declare SalesSums CURSOR FOR

Select  distinct SalesPerson from Sales

Open SalesSums

Fetch SalesSums INTO @SalesPerson

While @@Fetch_Status = 0

Begin
 Insert into @results Select Sales.Salesperson, sum(sales), sum(Gross), sum(profit) from Sales group by Sales.Salesperson having Sales.Salesperson = @SalesPerson
 Insert into @results Select 'EveryoneElse', avg(sales), avg(Gross), avg(profit) from Sales where Salesperson <> @SalesPerson

Fetch SalesSums INTO @SalesPerson          
End
Select * from @results
Close SalesSums
Deallocate SalesSums
Return