2017-01-22 112 views
0

对于家庭作业,我试图在2012年1月使用AdventureWorks2014查找每位销售人员的畅销产品。使用SQL Server,我如何才能在AdventureWorks2014中找到每个销售人员的畅销产品?

这是我到目前为止有:

SELECT  
    Person.Person.LastName, Person.Person.FirstName, 
    Person.Person.MiddleName, 
    Employee_1.JobTitle, 
    Sales.SalesPerson.SalesQuota, Sales.SalesOrderHeader.OrderDate, 
    Production.Product.Name, 
    SUM(distinct OrderQty) AS Expr2 
FROM 
    Sales.SalesOrderDetail 
INNER JOIN 
    Production.Product ON Sales.SalesOrderDetail.ProductID = Production.Product.ProductID 
INNER JOIN 
    Sales.SalesOrderHeader ON Sales.SalesOrderDetail.SalesOrderID = Sales.SalesOrderHeader.SalesOrderID 
          AND Sales.SalesOrderDetail.SalesOrderID = Sales.SalesOrderHeader.SalesOrderID 
          AND Sales.SalesOrderDetail.SalesOrderID = Sales.SalesOrderHeader.SalesOrderID 
INNER JOIN 
    Sales.SalesPerson ON Sales.SalesOrderHeader.SalesPersonID = Sales.SalesPerson.BusinessEntityID 
         AND Sales.SalesOrderHeader.SalesPersonID = Sales.SalesPerson.BusinessEntityID 
         AND Sales.SalesOrderHeader.SalesPersonID = Sales.SalesPerson.BusinessEntityID 
         AND Sales.SalesOrderHeader.SalesPersonID = Sales.SalesPerson.BusinessEntityID 
INNER JOIN 
    HumanResources.Employee AS Employee_1 
INNER JOIN 
    Person.Person ON Employee_1.BusinessEntityID = Person.Person.BusinessEntityID 
     ON Sales.SalesPerson.BusinessEntityID = Employee_1.BusinessEntityID 
     AND Sales.SalesPerson.BusinessEntityID = Employee_1.BusinessEntityID 
WHERE  
    (Sales.SalesOrderHeader.OrderDate BETWEEN '2012-01-01' AND '2012-01-31') 
GROUP BY 
    Person.Person.LastName, Person.Person.FirstName, Person.Person.MiddleName, 
    Employee_1.JobTitle, 
    Sales.SalesPerson.SalesQuota, Sales.SalesOrderHeader.OrderDate, 
    Production.Product.Name 
ORDER BY 
    Person.Person.LastName, Production.Product.Name 

我无法弄清楚如何添加orderqty所有为每个单独的产品。在前两排结果中,我有同一人销售的同一产品。我想将这些添加到一起,然后找到每个销售人员拥有的前5名产品?

任何人都可以帮忙吗?

+0

您需要使用RANK()和PARTITION BY。这里有很多例子,比如www.mikesknowledgebase.com/pages/SQLServer/Rank.htm –

+0

@MikeGledhill [sql server'rank()'''row_number()'](http://stackoverflow.com/问题/ 7747327/sql-rank-versus-row-number) - 我想你的意思是'row_number()' – SqlZim

回答

0

我最初的目标是将聚合数据集减少到最少的所需数量表以执行聚合(SalesOrderHeader, SalesOrderDetail)并将其与附加信息(例如Person, Employee)结合到表中。

我包含在聚合子查询的Product表,但它可以在聚合查询后进行,并加入到产品编号代替(将其添加到group byselect后)。


有很多方法可以做到这一点,这里有一些:

交叉apply版本:

select 
     p.LastName 
    , p.FirstName 
    , p.MiddleName 
    , e.JobTitle 
    , s.SalesQuota 
    , s.OrderDate 
    , s.ProductName 
    , s.TotalQty 
    from Person.Person as p on 
    inner join HumanResources.Employee as e on e.BusinessEntityID = p.BusinessEntityID 
    cross apply ( 
     select top 5 /* 5 rows */ 
     soh.SalesPersonID 
     , p.ProductName 
     , TotalQty = sum(OrderQty) 
     from Sales.SalesOrderHeader as soh 
     inner join Sales.SalesOrderDetail sod on soh.SalesOrderID = sod.SalesOrderID 
     inner join Production.Product as pr on sod.ProductID = pr.ProductID 
     where soh.OrderDate between '2012-01-01' and '2012-01-31' 
      and s.SalesPersonID = p.BusinessEntityID /* per person */ 
     group by soh.SalesPersonID, p.ProductName 
     order by sum(OrderQty) desc 
     /* ordered by sum(OrderQty) descending */ 
    ) s 

top with ties版本:

select top 5 with ties 
    p.LastName 
    , p.FirstName 
    , p.MiddleName 
    , e.JobTitle 
    , s.SalesQuota 
    , s.OrderDate 
    , s.ProductName 
    , s.TotalQty 
    from Person.Person as p on 
     inner join HumanResources.Employee as e on e.BusinessEntityID = p.BusinessEntityID 
     inner join ( 
     select 
      soh.SalesPersonID 
     , p.ProductName 
     , TotalQty = sum(OrderQty) 
     from Sales.SalesOrderHeader as soh 
      inner join Sales.SalesOrderDetail sod on soh.SalesOrderID = sod.SalesOrderID 
      inner join Production.Product as pr on sod.ProductID = pr.ProductID 
      where soh.OrderDate between '2012-01-01' and '2012-01-31' 
      group by soh.SalesPersonID, p.ProductName 
    ) on s.SalesPersonID = p.BusinessEntityID 
order by row_number() over (partition by p.BusinessEntityID order by s.TotalQty desc) 
/* returns all rows where row_number() over() evaluates to 1,2,3,4 ,or 5 */ 

common table expressionrow_number()版本:

with top5 as (
select 
     p.LastName 
    , p.FirstName 
    , p.MiddleName 
    , e.JobTitle 
    , s.SalesQuota 
    , s.OrderDate 
    , s.ProductName 
    , s.TotalQty 
    , rn=row_number() over (partition by p.BusinessEntityID order by s.TotalQty desc) 
    from Person.Person as p on 
    inner join HumanResources.Employee as e on e.BusinessEntityID = p.BusinessEntityID 
    inner join ( 
     select 
     soh.SalesPersonID 
     , p.ProductName 
     , TotalQty = sum(OrderQty) 
     from Sales.SalesOrderHeader as soh 
     inner join Sales.SalesOrderDetail sod on soh.SalesOrderID = sod.SalesOrderID 
     inner join Production.Product as pr on sod.ProductID = pr.ProductID 
     where soh.OrderDate between '2012-01-01' and '2012-01-31' 
     group by soh.SalesPersonID, p.ProductName 
    ) on s.SalesPersonID = p.BusinessEntityID 
) 

select 
     LastName 
    , FirstName 
    , MiddleName 
    , JobTitle 
    , SalesQuota 
    , OrderDate 
    , ProductName 
    , TotalQty 
    from top5 
    where rn < 6