使用SQL Server,如何在AdventureWorks2014中找到每个销售人员的畅销产品?

时间:2017-01-22 16:00:43

标签: sql sql-server adventureworks

对于家庭作业,我试图在2012年1月使用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个产品?

有人可以帮忙吗?

1 个答案:

答案 0 :(得分:0)

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

我在聚合子查询中包含了Product表,但是可以在聚合查询之后完成并加入到ProductId(将其添加到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 expression

row_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